Change the kernel dev_t, representing a pointer to a specinfo structure,
[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.19 2006/09/10 01:26:38 dillon 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                         printf("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                         printf("meteor%d: 0x%x i2c %s tranfer aborted",
506                                 METEOR_NUM(mtr), slave,
507                                 rw ? "read" : "write" );
508                 err= 1;
509         }
510
511         if(err) {
512                 if(i2c_print_err)
513                         printf(" - 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 ((char *)0);
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                 printf("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                 printf("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                         printf("meteor%d: capture error", METEOR_NUM(mtr));
580                         printf(": %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                         printf("meteor%d: capture error", METEOR_NUM(mtr));
588                         printf(": %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                 printf("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                 printf("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                 printf("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                 printf("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                 printf("meteor%d: attach: only %d units configured.\n",
1002                                 unit, NMETEOR);
1003                 printf("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                                 printf("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         printf("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                         printf("meteor%d: PCI bus latency is", unit);
1066                 else
1067                         printf("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                 printf(" %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                 printf("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 = (struct proc *)0;
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 = (struct proc *)0;
1220
1221 #ifdef METEOR_DEALLOC_PAGES
1222         if (mtr->bigbuf != NULL) {
1223                 kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE));
1224                 mtr->bigbuf = NULL;
1225                 mtr->alloc_pages = 0;
1226         }
1227 #else
1228 #ifdef METEOR_DEALLOC_ABOVE
1229         if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) {
1230                 temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages;
1231                 kmem_free(kernel_map,
1232                           mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE),
1233                           (temp * PAGE_SIZE));
1234                 mtr->alloc_pages = METEOR_DEALLOC_ABOVE;
1235         }
1236 #endif
1237 #endif
1238
1239         return(0);
1240 }
1241
1242 static void
1243 start_capture(meteor_reg_t *mtr, unsigned type)
1244 {
1245 mreg_t *cap = &mtr->base->cap_cntl;
1246
1247         mtr->flags |= type;
1248         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1249         case METEOR_ONLY_EVEN_FIELDS:
1250                 mtr->flags |= METEOR_WANT_EVEN;
1251                 if(type == METEOR_SINGLE)
1252                         *cap = 0x0ff4 | mtr->range_enable;
1253                 else
1254                         *cap = 0x0ff1 | mtr->range_enable;
1255                 break;
1256         case METEOR_ONLY_ODD_FIELDS:
1257                 mtr->flags |= METEOR_WANT_ODD;
1258                 if(type == METEOR_SINGLE)
1259                         *cap = 0x0ff8 | mtr->range_enable;
1260                 else
1261                         *cap = 0x0ff2 | mtr->range_enable;
1262                 break;
1263         default:
1264                 mtr->flags |= METEOR_WANT_MASK;
1265                 if(type == METEOR_SINGLE)
1266                         *cap = 0x0ffc | mtr->range_enable;
1267                 else
1268                         *cap = 0x0ff3 | mtr->range_enable;
1269                 break;
1270         }
1271 }
1272
1273 int
1274 meteor_read(struct dev_read_args *ap)
1275 {
1276         cdev_t dev = ap->a_head.a_dev;
1277         struct uio *uio = ap->a_uio;
1278         meteor_reg_t *mtr;
1279         int     unit; 
1280         int     status;
1281         int     count;
1282
1283         unit = UNIT(minor(dev));
1284         if (unit >= NMETEOR)    /* unit out of range */
1285                 return(ENXIO);
1286
1287         mtr = &(meteor[unit]);
1288         if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */
1289                 return(ENOMEM);
1290
1291         if (mtr->flags & METEOR_CAP_MASK)
1292                 return(EIO);            /* already capturing */
1293
1294         count = mtr->rows * mtr->cols * mtr->depth;
1295         if (uio->uio_iov->iov_len < count)
1296                 return(EINVAL);
1297
1298         /* Start capture */
1299         start_capture(mtr, METEOR_SINGLE);
1300
1301         status=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1302         if (!status)            /* successful capture */
1303                 status = uiomove((caddr_t)mtr->bigbuf, count, uio);
1304         else
1305                 printf ("meteor%d: read: tsleep error %d\n", unit, status);
1306
1307         mtr->flags &= ~(METEOR_SINGLE | METEOR_WANT_MASK);
1308
1309         return(status);
1310 }
1311
1312 int
1313 meteor_write(struct dev_write_args *ap)
1314 {
1315         return(0);
1316 }
1317
1318 int
1319 meteor_ioctl(struct dev_ioctl_args *ap)
1320 {
1321         cdev_t dev = ap->a_head.a_dev;
1322         caddr_t data = ap->a_data;
1323         int     error;  
1324         int     unit;   
1325         unsigned int    temp;
1326         meteor_reg_t *mtr;
1327         struct meteor_counts *cnt;
1328         struct meteor_geomet *geo;
1329         struct meteor_mem *mem;
1330         struct meteor_capframe *frame;
1331 #ifdef METEOR_TEST_VIDEO
1332         struct meteor_video *video;
1333 #endif
1334         vm_offset_t buf;
1335         struct saa7116_regs *base;
1336
1337         error = 0;
1338
1339         if (data == NULL)
1340                 return(EINVAL);
1341         unit = UNIT(minor(dev));
1342         if (unit >= NMETEOR)    /* unit out of range */
1343                 return(ENXIO);
1344
1345         mtr = &(meteor[unit]);
1346         base = mtr->base;
1347
1348         switch (ap->a_cmd) {
1349         case METEORSTS:
1350                 if(*data)
1351                         mtr->flags |= METEOR_WANT_TS;
1352                 else
1353                         mtr->flags &= ~METEOR_WANT_TS;
1354                 break;
1355         case METEORGTS:
1356                 if(mtr->flags & METEOR_WANT_TS)
1357                         *data = 1;
1358                 else
1359                         *data = 0;
1360                 break;
1361 #ifdef METEOR_TEST_VIDEO
1362         case METEORGVIDEO:
1363                 video = (struct meteor_video *)data;
1364                 video->addr = mtr->video.addr;
1365                 video->width = mtr->video.width;
1366                 video->banksize = mtr->video.banksize;
1367                 video->ramsize = mtr->video.ramsize;
1368                 break;
1369         case METEORSVIDEO:
1370                 video = (struct meteor_video *)data;
1371                 mtr->video.addr = video->addr;
1372                 mtr->video.width = video->width;
1373                 mtr->video.banksize = video->banksize;
1374                 mtr->video.ramsize = video->ramsize;
1375                 break;
1376 #endif
1377         case METEORSFPS:
1378                 set_fps(mtr, *(u_short *)data);
1379                 break;
1380         case METEORGFPS:
1381                 *(u_short *)data = mtr->fps;
1382                 break;
1383         case METEORSSIGNAL:
1384                 if (*(int *)data < 0 || *(int *)data > _SIG_MAXSIG)
1385                         return EINVAL;
1386                 mtr->signal = *(int *) data;
1387                 if (mtr->signal) {
1388                   mtr->proc = curproc;  /* might be NULL */
1389                 } else {
1390                   mtr->proc = (struct proc *)0;
1391                 }
1392                 break;
1393         case METEORGSIGNAL:
1394                 *(int *)data = mtr->signal;
1395                 break;
1396         case METEORSTATUS:      /* get 7196 status */
1397                 temp = 0;
1398                 SAA7196_WRITE(mtr, SAA7196_STDC,
1399                         SAA7196_REG(mtr, SAA7196_STDC) | 0x02);
1400                 SAA7196_READ(mtr);
1401                 temp |= (base->i2c_read & 0xff000000L) >> 24;
1402                 SAA7196_WRITE(mtr, SAA7196_STDC,
1403                         SAA7196_REG(mtr, SAA7196_STDC) & ~0x02);
1404                 SAA7196_READ(mtr);
1405                 temp |= (base->i2c_read & 0xff000000L) >> 16;
1406                 *(u_short *)data = temp;
1407                 break;
1408         case METEORSHUE:        /* set hue */
1409                 SAA7196_WRITE(mtr, SAA7196_HUEC, *(char *)data);
1410                 break;
1411         case METEORGHUE:        /* get hue */
1412                 *(char *)data = SAA7196_REG(mtr, SAA7196_HUEC);
1413                 break;
1414         case METEORSCHCV:       /* set chrominance gain */
1415                 SAA7196_WRITE(mtr, SAA7196_CGAINR, *(char *)data);
1416                 break;
1417         case METEORGCHCV:       /* get chrominance gain */
1418                 *(char *)data = SAA7196_REG(mtr, SAA7196_CGAINR);
1419                 break;
1420         case METEORSBRIG:       /* set brightness */
1421                 SAA7196_WRITE(mtr, SAA7196_BRIG, *(char *)data);
1422                 break;
1423         case METEORGBRIG:       /* get brightness */
1424                 *(char *)data = SAA7196_REG(mtr, SAA7196_BRIG);
1425                 break;
1426         case METEORSCSAT:       /* set chroma saturation */
1427                 SAA7196_WRITE(mtr, SAA7196_CSAT, *(char *)data);
1428                 break;
1429         case METEORGCSAT:       /* get chroma saturation */
1430                 *(char *)data = SAA7196_REG(mtr, SAA7196_CSAT);
1431                 break;
1432         case METEORSCONT:       /* set contrast */
1433                 SAA7196_WRITE(mtr, SAA7196_CONT, *(char *)data);
1434                 break;
1435         case METEORGCONT:       /* get contrast */
1436                 *(char *)data = SAA7196_REG(mtr, SAA7196_CONT);
1437                 break;
1438         case METEORSBT254:
1439                 if((mtr->flags & METEOR_RGB) == 0)
1440                         return EINVAL;
1441                 temp = *(unsigned short *)data;
1442                 bt254_write(mtr, temp & 0xf, (temp & 0x0ff0) >> 4);
1443                 break;
1444         case METEORGBT254:
1445                 if((mtr->flags & METEOR_RGB) == 0)
1446                         return EINVAL;
1447                 temp = *(unsigned short *)data & 0x7;
1448                 *(unsigned short *)data = mtr->bt254_reg[temp] << 4 | temp;
1449                 break;
1450         case METEORSHWS:        /* set horizontal window start */
1451                 SAA7196_WRITE(mtr, SAA7196_HWS, *(char *)data);
1452                 break;
1453         case METEORGHWS:        /* get horizontal window start */
1454                 *(char *)data = SAA7196_REG(mtr, SAA7196_HWS);
1455                 break;
1456         case METEORSVWS:        /* set vertical window start */
1457                 SAA7196_WRITE(mtr, SAA7196_VWS, *(char *)data);
1458                 break;
1459         case METEORGVWS:        /* get vertical window start */
1460                 *(char *)data = SAA7196_REG(mtr, SAA7196_VWS);
1461                 break;
1462         case METEORSINPUT:      /* set input device */
1463                 switch(*(unsigned long *)data & METEOR_DEV_MASK) {
1464                 case 0:                 /* default */
1465                 case METEOR_INPUT_DEV0:
1466                         if(mtr->flags & METEOR_RGB)
1467                                 select_saa7196(mtr);
1468                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1469                                 | METEOR_DEV0;
1470                         SAA7196_WRITE(mtr, 0x0e,
1471                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0);
1472                         SAA7196_WRITE(mtr, 0x06,
1473                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1474                         break;
1475                 case METEOR_INPUT_DEV1:
1476                         if(mtr->flags & METEOR_RGB)
1477                                 select_saa7196(mtr);
1478                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1479                                                | METEOR_DEV1;
1480                         SAA7196_WRITE(mtr, 0x0e,
1481                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1);
1482                         SAA7196_WRITE(mtr, 0x06,
1483                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1484                         break;
1485                 case METEOR_INPUT_DEV2:
1486                         if(mtr->flags & METEOR_RGB)
1487                                 select_saa7196(mtr);
1488                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1489                                                | METEOR_DEV2;
1490                         SAA7196_WRITE(mtr, 0x0e,
1491                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1492                         SAA7196_WRITE(mtr, 0x06,
1493                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1494                         break;
1495                 case METEOR_INPUT_DEV3:
1496                         if(mtr->flags & METEOR_RGB)
1497                                 select_saa7196(mtr);
1498                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1499                                                | METEOR_DEV3;
1500                         SAA7196_WRITE(mtr, 0x0e,
1501                                 (SAA7196_REG(mtr, 0x0e) | 0x3));
1502                         SAA7196_WRITE(mtr, 0x06,
1503                                 (SAA7196_REG(mtr, 0x06) & ~0x80) );
1504                         break;
1505                 case METEOR_INPUT_DEV_SVIDEO:
1506                         if(mtr->flags & METEOR_RGB)
1507                                 select_saa7196(mtr);
1508                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1509                                                | METEOR_DEV_SVIDEO;
1510                         SAA7196_WRITE(mtr, 0x0e,
1511                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2);
1512                         SAA7196_WRITE(mtr, 0x06,
1513                                 (SAA7196_REG(mtr, 0x06) & ~0x80) | 0x80);
1514                         break;
1515                 case METEOR_INPUT_DEV_RGB:
1516                         if((mtr->flags & METEOR_RGB) == 0)
1517                                 return EINVAL;
1518                         mtr->flags = (mtr->flags & ~METEOR_DEV_MASK)
1519                                                | METEOR_DEV_RGB;
1520                         SAA7196_WRITE(mtr, 0x0e,
1521                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1522                         SAA7196_WRITE(mtr, 0x06,
1523                                 (SAA7196_REG(mtr, 0x06) & ~0x80));
1524                         select_bt254(mtr);
1525                         SAA7196_WRITE(mtr, 0x0e,        /* chn 3 for synch */
1526                                 (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x3);
1527                         break;
1528                 default:
1529                         return EINVAL;
1530                 }
1531                 break;
1532         case METEORGINPUT:      /* get input device */
1533                 *(u_long *)data = mtr->flags & METEOR_DEV_MASK;
1534                 break;
1535         case METEORSFMT:        /* set input format */
1536                 switch(*(unsigned long *)data & METEOR_FORM_MASK ) {
1537                 case 0:                 /* default */
1538                 case METEOR_FMT_NTSC:
1539                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1540                                 METEOR_NTSC;
1541                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1542                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1543                         SAA7196_WRITE(mtr, 0x0f,
1544                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x40);
1545                         SAA7196_WRITE(mtr, 0x22, 0x80);
1546                         SAA7196_WRITE(mtr, 0x24, 
1547                                 (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08);
1548                         SAA7196_WRITE(mtr, 0x26, 0xf0);
1549                         SAA7196_WRITE(mtr, 0x28, 
1550                                 (SAA7196_REG(mtr, 0x28) & ~0x0c)) ;
1551                         if(mtr->flags & METEOR_RGB){
1552                           bt254_ntsc(mtr, 1);                     
1553                         }
1554                 break;
1555                 case METEOR_FMT_PAL:
1556                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1557                                 METEOR_PAL;
1558                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1559                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1560                         SAA7196_WRITE(mtr, 0x0f, 
1561                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0));
1562                         SAA7196_WRITE(mtr, 0x22, 0x00);
1563                         SAA7196_WRITE(mtr, 0x24, 
1564                                 (SAA7196_REG(mtr, 0x24) | 0x0c));
1565                         SAA7196_WRITE(mtr, 0x26, 0x20);
1566                         SAA7196_WRITE(mtr, 0x28, 
1567                                 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1568                         if(mtr->flags & METEOR_RGB){
1569                           bt254_ntsc(mtr, 0);                     
1570                         }
1571                 break;
1572                 case METEOR_FMT_SECAM:
1573                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1574                                 METEOR_SECAM;
1575                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1576                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01) | 0x1);
1577                         SAA7196_WRITE(mtr, 0x0f, 
1578                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x20);
1579                         SAA7196_WRITE(mtr, 0x22, 0x00);
1580                         SAA7196_WRITE(mtr, 0x24, 
1581                                 (SAA7196_REG(mtr, 0x24) | 0x0c));
1582                         SAA7196_WRITE(mtr, 0x26, 0x20);
1583                         SAA7196_WRITE(mtr, 0x28, 
1584                                 (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x04) ;
1585                         if(mtr->flags & METEOR_RGB){
1586                           bt254_ntsc(mtr, 0);
1587                         }
1588                 break;
1589                 case METEOR_FMT_AUTOMODE:
1590                         mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) |
1591                                 METEOR_AUTOMODE;
1592                         SAA7196_WRITE(mtr, SAA7196_STDC, 
1593                                 (SAA7196_REG(mtr, SAA7196_STDC) & ~0x01));
1594                         SAA7196_WRITE(mtr, 0x0f, 
1595                                 (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0x80);
1596                 break;
1597                 default:
1598                         return EINVAL;
1599                 }
1600                 break;
1601         case METEORGFMT:        /* get input format */
1602                 *(u_long *)data = mtr->flags & METEOR_FORM_MASK;
1603                 break;
1604         case METEORCAPTUR:
1605                 temp = mtr->flags;
1606                 switch (*(int *) data) {
1607                 case METEOR_CAP_SINGLE:
1608                         if (mtr->bigbuf==0)     /* no frame buffer allocated */
1609                                 return(ENOMEM);
1610
1611                         if (temp & METEOR_CAP_MASK)
1612                                 return(EIO);            /* already capturing */
1613
1614                         start_capture(mtr, METEOR_SINGLE);
1615
1616                         /* wait for capture to complete */
1617                         error=tsleep((caddr_t)mtr, METPRI, "capturing", 0);
1618                         if(error)
1619                                 printf("meteor%d: ioctl: tsleep error %d\n",
1620                                         unit, error);
1621                         mtr->flags &= ~(METEOR_SINGLE|METEOR_WANT_MASK);
1622                         break;
1623                 case METEOR_CAP_CONTINOUS:
1624                         if (mtr->bigbuf==0)     /* no frame buffer allocated */
1625                                 return(ENOMEM);
1626
1627                         if (temp & METEOR_CAP_MASK)
1628                                 return(EIO);            /* already capturing */
1629
1630                         start_capture(mtr, METEOR_CONTIN);
1631
1632                         break;
1633                 case METEOR_CAP_STOP_CONT:
1634                         if (mtr->flags & METEOR_CONTIN) {
1635                                                         /* turn off capture */
1636                                 base->cap_cntl = 0x8ff0;
1637                                 mtr->flags &= ~(METEOR_CONTIN|METEOR_WANT_MASK);
1638                         }
1639                         break;
1640         
1641                 default:
1642                         error = EINVAL;
1643                         break;
1644                 }
1645                 break;
1646         case METEORCAPFRM:
1647             frame = (struct meteor_capframe *) data;
1648             if (!frame) 
1649                 return(EINVAL);
1650             switch (frame->command) {
1651             case METEOR_CAP_N_FRAMES:
1652                 if (mtr->flags & METEOR_CAP_MASK)
1653                         return(EIO);
1654                 if (mtr->flags & (METEOR_YUV_PLANAR | METEOR_YUV_422)) /* XXX */
1655                         return(EINVAL); /* should fix intr so we allow these */
1656                 if (mtr->bigbuf == 0)
1657                         return(ENOMEM);
1658                 if ((mtr->frames < 2) ||
1659                     (frame->lowat < 1 || frame->lowat >= mtr->frames) ||
1660                     (frame->hiwat < 1 || frame->hiwat >= mtr->frames) ||
1661                     (frame->lowat > frame->hiwat)) 
1662                         return(EINVAL);
1663                         /* meteor_mem structure is on the page after the data */
1664                 mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf +
1665                                 (round_page(mtr->frame_size * mtr->frames)));
1666                 mtr->current = 1;
1667                 mtr->synch_wait = 0;
1668                 mem->num_bufs = mtr->frames;
1669                 mem->frame_size= mtr->frame_size;
1670                 /* user and kernel change these */ 
1671                 mem->lowat = frame->lowat;
1672                 mem->hiwat = frame->hiwat;
1673                 mem->active = 0;
1674                 mem->num_active_bufs = 0;
1675                 /* Start capture */
1676                 start_capture(mtr, METEOR_SYNCAP);
1677                 break;
1678             case METEOR_CAP_STOP_FRAMES:
1679                 if (mtr->flags & METEOR_SYNCAP) {
1680                                                 /* turn off capture */
1681                         base->cap_cntl = 0x8ff0;
1682                         mtr->flags &= ~(METEOR_SYNCAP|METEOR_WANT_MASK);
1683                 }
1684                 break;
1685             case METEOR_HALT_N_FRAMES:
1686                 if(mtr->flags & METEOR_SYNCAP) {
1687                         base->cap_cntl = 0x8ff0;
1688                         mtr->flags &= ~(METEOR_WANT_MASK);
1689                 }
1690                 break;
1691             case METEOR_CONT_N_FRAMES:
1692                 if(!(mtr->flags & METEOR_SYNCAP)) {
1693                         error = EINVAL;
1694                         break;
1695                 }
1696                 start_capture(mtr, METEOR_SYNCAP);
1697                 break;
1698             default:
1699                 error = EINVAL;
1700                 break;
1701             }
1702             break;
1703  
1704         case METEORSETGEO:
1705                 geo = (struct meteor_geomet *) data;
1706
1707                 /* Either even or odd, if even & odd, then these a zero */
1708                 if((geo->oformat & METEOR_GEO_ODD_ONLY) &&
1709                         (geo->oformat & METEOR_GEO_EVEN_ONLY)) {
1710                         printf("meteor%d: ioctl: Geometry odd or even only.\n",
1711                                 unit);
1712                         return EINVAL;
1713                 }
1714                 /* set/clear even/odd flags */
1715                 if(geo->oformat & METEOR_GEO_ODD_ONLY)
1716                         mtr->flags |= METEOR_ONLY_ODD_FIELDS;
1717                 else
1718                         mtr->flags &= ~METEOR_ONLY_ODD_FIELDS;
1719                 if(geo->oformat & METEOR_GEO_EVEN_ONLY)
1720                         mtr->flags |= METEOR_ONLY_EVEN_FIELDS;
1721                 else
1722                         mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS;
1723
1724                 /* can't change parameters while capturing */
1725                 if (mtr->flags & METEOR_CAP_MASK)
1726                         return(EBUSY);
1727
1728                 if ((geo->columns & 0x3fe) != geo->columns) {
1729                         printf(
1730                         "meteor%d: ioctl: %d: columns too large or not even.\n",
1731                                 unit, geo->columns);
1732                         error = EINVAL;
1733                 }
1734                 if (((geo->rows & 0x7fe) != geo->rows) ||
1735                         ((geo->oformat & METEOR_GEO_FIELD_MASK) &&
1736                                 ((geo->rows & 0x3fe) != geo->rows)) ) {
1737                         printf(
1738                         "meteor%d: ioctl: %d: rows too large or not even.\n",
1739                                 unit, geo->rows);
1740                         error = EINVAL;
1741                 }
1742                 if (geo->frames > 32) {
1743                         printf("meteor%d: ioctl: too many frames.\n", unit);
1744                         error = EINVAL;
1745                 }
1746                 if(error) return error;
1747
1748                 if ((temp=geo->rows * geo->columns * geo->frames * 2) != 0) {
1749                         if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2;
1750
1751                         /* meteor_mem structure for SYNC Capture */
1752                         if (geo->frames > 1) temp += PAGE_SIZE;
1753
1754                         temp = btoc(temp);
1755                         if (temp > mtr->alloc_pages
1756 #ifdef METEOR_TEST_VIDEO
1757                             && mtr->video.addr == 0
1758 #endif
1759                         ) {
1760                                 buf = get_meteor_mem(unit, temp*PAGE_SIZE);
1761                                 if(buf != 0) {
1762                                         kmem_free(kernel_map, mtr->bigbuf,
1763                                           (mtr->alloc_pages * PAGE_SIZE));
1764                                         mtr->bigbuf = buf;
1765                                         mtr->alloc_pages = temp;
1766                                         if(bootverbose)
1767                                                 printf(
1768                                 "meteor%d: ioctl: Allocating %d bytes\n",
1769                                                         unit, temp*PAGE_SIZE);
1770                                 } else {
1771                                         error = ENOMEM;
1772                                 }
1773                         }
1774                 }
1775                 if(error) return error;
1776
1777                 mtr->rows = geo->rows;
1778                 mtr->cols = geo->columns;
1779                 mtr->frames = geo->frames;
1780
1781 #ifdef METEOR_TEST_VIDEO
1782                 if(mtr->video.addr)
1783                         buf = vtophys(mtr->video.addr);
1784                 else
1785 #endif
1786                         buf = vtophys(mtr->bigbuf);
1787
1788                 /* set defaults and end of buffer locations */
1789                 base->dma1e = buf;
1790                 base->dma2e = buf;
1791                 base->dma3e = buf;
1792                 base->dma1o = buf;
1793                 base->dma2o = buf;
1794                 base->dma3o = buf;
1795                 base->stride1e = 0;
1796                 base->stride2e = 0;
1797                 base->stride3e = 0;
1798                 base->stride1o = 0;
1799                 base->stride2o = 0;
1800                 base->stride3o = 0;
1801                                 /* set end of DMA location, even/odd */
1802                 base->dma_end_e =
1803                 base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE;
1804
1805                 /*
1806                  * Determine if we can use the hardware range detect.
1807                  */
1808                 if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY &&
1809                   ((buf & 0xff000000) | base->dma_end_e) ==
1810                         (buf + mtr->alloc_pages * PAGE_SIZE) )
1811                         mtr->range_enable = 0x8000;
1812                 else {
1813                         mtr->range_enable = 0x0;
1814                         base->dma_end_e =
1815                         base->dma_end_o = 0xffffffff;
1816                 }
1817
1818
1819                 switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) {
1820                 case 0:                 /* default */
1821                 case METEOR_GEO_RGB16:
1822                         mtr->depth = 2;
1823                         mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1824                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1825                         mtr->flags |= METEOR_RGB16;
1826                         temp = mtr->cols * mtr->depth;
1827                         /* recal stride and starting point */
1828                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1829                         case METEOR_ONLY_ODD_FIELDS:
1830                                 base->dma1o = buf;
1831 #ifdef METEOR_TEST_VIDEO
1832                                 if(mtr->video.addr && mtr->video.width) 
1833                                         base->stride1o = mtr->video.width-temp;
1834 #endif
1835                                 SAA7196_WRITE(mtr, 0x20, 0xd0);
1836                                 break;
1837                         case METEOR_ONLY_EVEN_FIELDS:
1838                                 base->dma1e = buf;
1839 #ifdef METEOR_TEST_VIDEO
1840                                 if(mtr->video.addr && mtr->video.width) 
1841                                         base->stride1e = mtr->video.width-temp;
1842 #endif
1843                                 SAA7196_WRITE(mtr, 0x20, 0xf0);
1844                                 break;
1845                         default: /* interlaced even/odd */
1846                                 base->dma1e = buf;              
1847                                 base->dma1o = buf + temp;
1848                                 base->stride1e = base->stride1o = temp;
1849 #ifdef METEOR_TEST_VIDEO
1850                                 if(mtr->video.addr && mtr->video.width) {
1851                                         base->dma1o = buf + mtr->video.width;
1852                                         base->stride1e = base->stride1o =
1853                                                 mtr->video.width -
1854                                                 temp + mtr->video.width;
1855                                 }
1856 #endif
1857                                 SAA7196_WRITE(mtr, 0x20, 0x90);
1858                                 break;
1859                         }
1860                         base->routee = base->routeo  = 0xeeeeee01;
1861                         break;
1862                 case METEOR_GEO_RGB24:
1863                         mtr->depth = 4;
1864                         mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
1865                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1866                         mtr->flags |= METEOR_RGB24;
1867                         temp = mtr->cols * mtr->depth;
1868                         /* recal stride and starting point */
1869                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1870                         case METEOR_ONLY_ODD_FIELDS:
1871                                 base->dma1o = buf;
1872 #ifdef METEOR_TEST_VIDEO
1873                                 if(mtr->video.addr && mtr->video.width) 
1874                                         base->stride1o = mtr->video.width-temp;
1875 #endif
1876                                 SAA7196_WRITE(mtr, 0x20, 0xd2);
1877                                 break;
1878                         case METEOR_ONLY_EVEN_FIELDS:
1879                                 base->dma1e = buf;
1880 #ifdef METEOR_TEST_VIDEO
1881                                 if(mtr->video.addr && mtr->video.width) 
1882                                         base->stride1e = mtr->video.width-temp;
1883 #endif
1884                                 SAA7196_WRITE(mtr, 0x20, 0xf2);
1885                                 break;
1886                         default: /* interlaced even/odd */
1887                                 base->dma1e = buf;
1888                                 base->dma1o = buf + mtr->cols * mtr->depth;
1889                                 base->stride1e = base->stride1o =
1890                                         mtr->cols * mtr->depth;
1891 #ifdef METEOR_TEST_VIDEO
1892                                 if(mtr->video.addr && mtr->video.width) {
1893                                         base->dma1o = buf + mtr->video.width;
1894                                         base->stride1e = base->stride1o = 
1895                                                 mtr->video.width -
1896                                                 temp + mtr->video.width;
1897                                 }
1898 #endif
1899                                 SAA7196_WRITE(mtr, 0x20, 0x92);
1900                                 break;
1901                         }
1902                         base->routee= base->routeo= 0x39393900;
1903                         break;
1904                 case METEOR_GEO_YUV_PLANAR:
1905                         mtr->depth = 2;
1906                         temp = mtr->rows * mtr->cols;   /* compute frame size */
1907                         mtr->frame_size = temp * mtr->depth;
1908                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1909                         mtr->flags |= METEOR_YUV_PLANAR;
1910                         /* recal stride and starting point */
1911                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1912                         case METEOR_ONLY_ODD_FIELDS:
1913                                 base->dma1o = buf;              /* Y Odd */
1914                                 base->dma2o = buf + temp;       /* U Odd */
1915                                 temp >>= 1;
1916                                 base->dma3o = base->dma2o + temp; /* V Odd */
1917                                 SAA7196_WRITE(mtr, 0x20, 0xd1);
1918                                 break;
1919                         case METEOR_ONLY_EVEN_FIELDS:
1920                                 base->dma1e = buf;              /* Y Even */
1921                                 base->dma2e = buf + temp;       /* U Even */
1922                                 temp >>= 1;
1923                                 base->dma2e= base->dma2e + temp; /* V Even */
1924                                 SAA7196_WRITE(mtr, 0x20, 0xf1);
1925                                 break;
1926                         default: /* interlaced even/odd */
1927                                 base->dma1e = buf;              /* Y Even */
1928                                 base->dma2e = buf + temp;       /* U Even */
1929                                 temp >>= 2;
1930                                 base->dma3e = base->dma2e + temp; /* V Even */
1931                                 base->dma1o = base->dma1e+mtr->cols;/* Y Odd */
1932                                 base->dma2o = base->dma3e + temp; /* U Odd */
1933                                 base->dma3o = base->dma2o + temp; /* V Odd */
1934                                 base->stride1e = base->stride1o = mtr->cols;
1935                                 SAA7196_WRITE(mtr, 0x20, 0x91);
1936                                 break;
1937                         }
1938                         switch (geo->oformat &
1939                                 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1940                                 case METEOR_GEO_YUV_9:
1941                                         base->routee=base->routeo = 0xaaaaffc3;
1942                                         break;
1943                                 case METEOR_GEO_YUV_12:
1944                                         base->routee=base->routeo = 0xaaaaffc2;
1945                                         break;
1946                                 default:
1947                                         base->routee=base->routeo = 0xaaaaffc1;
1948                                         break;
1949                         }
1950                         break;
1951                 case METEOR_GEO_YUV_422:/* same as planer, different uv order */
1952                         mtr->depth = 2;
1953                         temp = mtr->rows * mtr->cols;   /* compute frame size */
1954                         mtr->frame_size = temp * mtr->depth;
1955                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
1956                         mtr->flags |= METEOR_YUV_422;
1957                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
1958                         case METEOR_ONLY_ODD_FIELDS:
1959                                 base->dma1o = buf;
1960                                 base->dma2o = buf + temp;
1961                                 base->dma3o = base->dma2o  + (temp >> 1);
1962                                 SAA7196_WRITE(mtr, 0x20, 0xd1);
1963                                 break;
1964                         case METEOR_ONLY_EVEN_FIELDS:
1965                                 base->dma1e = buf;
1966                                 base->dma2e = buf + temp;
1967                                 base->dma3e = base->dma2e + (temp >> 1);
1968                                 SAA7196_WRITE(mtr, 0x20, 0xf1);
1969                                 break;
1970                         default: /* interlaced even/odd */
1971                                 base->dma1e = buf;              /* Y even */
1972                                 base->dma2e = buf + temp;       /* U even */
1973                                 base->dma3e =
1974                                         base->dma2e + (temp >> 1);/* V even */
1975                                 base->dma1o = base->dma1e+mtr->cols;/* Y odd */
1976                                 temp = mtr->cols >> 1;
1977                                 base->dma2o = base->dma2e+temp; /* U odd */
1978                                 base->dma3o = base->dma3e+temp; /* V odd */
1979                                 base->stride1e =
1980                                 base->stride1o = mtr->cols;     /* Y stride */
1981                                 base->stride2e = 
1982                                 base->stride2o = temp;          /* U stride */
1983                                 base->stride3e =
1984                                 base->stride3o = temp;          /* V stride */
1985                                 SAA7196_WRITE(mtr, 0x20, 0x91);
1986                                 break;
1987                         }
1988                         switch (geo->oformat &
1989                                 (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) {
1990                                 case METEOR_GEO_YUV_9:
1991                                         base->routee=base->routeo = 0xaaaaffc3;
1992                                         break;
1993                                 case METEOR_GEO_YUV_12:
1994                                         base->routee=base->routeo = 0xaaaaffc2;
1995                                         break;
1996                                 default:
1997                                         base->routee=base->routeo = 0xaaaaffc1;
1998                                         break;
1999                         }
2000                         break;
2001                 case METEOR_GEO_YUV_PACKED:
2002                         mtr->depth = 2;
2003                         mtr->frame_size = mtr->rows * mtr->cols * mtr->depth;
2004                         mtr->flags &= ~METEOR_OUTPUT_FMT_MASK;
2005                         mtr->flags |= METEOR_YUV_PACKED;
2006                         /* recal stride and odd starting point */
2007                         switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2008                         case METEOR_ONLY_ODD_FIELDS:
2009                                 base->dma1o = buf;
2010                                 SAA7196_WRITE(mtr, 0x20, 0xd1);
2011                                 break;
2012                         case METEOR_ONLY_EVEN_FIELDS:
2013                                 base->dma1e = buf;
2014                                 SAA7196_WRITE(mtr, 0x20, 0xf1);
2015                                 break;
2016                         default: /* interlaced even/odd */
2017                                 base->dma1e = buf;
2018                                 base->dma1o = buf + mtr->cols * mtr->depth;
2019                                 base->stride1e = base->stride1o =
2020                                         mtr->cols * mtr->depth;
2021                                 SAA7196_WRITE(mtr, 0x20, 0x91);
2022                                 break;
2023                         }
2024                         base->routee = base->routeo = 0xeeeeee41;
2025                         break;
2026                 default:
2027                         error = EINVAL; /* invalid argument */
2028                         printf("meteor%d: ioctl: invalid output format\n",unit);
2029                         break;
2030                 }
2031                 /* set cols */
2032                 SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff);
2033                 SAA7196_WRITE(mtr, 0x24,
2034                                 ((SAA7196_REG(mtr, 0x24) & ~0x03) |
2035                                 ((mtr->cols >> 8) & 0x03)));
2036                 /* set rows */
2037                 if(mtr->flags & METEOR_ONLY_FIELDS_MASK) {
2038                         SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff));
2039                         SAA7196_WRITE(mtr, 0x28,
2040                                         ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2041                                         ((mtr->rows >> 8) & 0x03)));
2042                 } else {        /* Interlaced */
2043                         SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff));
2044                         SAA7196_WRITE(mtr, 0x28,
2045                                         ((SAA7196_REG(mtr, 0x28) & ~0x03) |
2046                                         ((mtr->rows >> 9) & 0x03)));
2047                 }
2048                 /* set signed/unsigned chrominance */
2049                 SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) |
2050                                 ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10));
2051                 break;
2052         case METEORGETGEO:
2053                 geo = (struct meteor_geomet *) data;
2054                 geo->rows = mtr->rows;
2055                 geo->columns = mtr->cols;
2056                 geo->frames = mtr->frames;
2057                 geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) |
2058                                (mtr->flags & METEOR_ONLY_FIELDS_MASK) |
2059                                (SAA7196_REG(mtr, 0x30) & 0x10 ? 
2060                                 0:METEOR_GEO_UNSIGNED);
2061                 switch(base->routee & 0xff) {
2062                 case    0xc3:
2063                         geo->oformat |=  METEOR_GEO_YUV_9;
2064                         break;
2065                 case    0xc2:
2066                         geo->oformat |=  METEOR_GEO_YUV_12;
2067                         break;
2068                 default:
2069                         break;
2070                 }
2071                 break;
2072         case METEORSCOUNT:      /* (re)set error counts */
2073                 cnt = (struct meteor_counts *) data;
2074                 mtr->fifo_errors = cnt->fifo_errors;
2075                 mtr->dma_errors = cnt->dma_errors;
2076                 mtr->frames_captured = cnt->frames_captured;
2077                 mtr->even_fields_captured = cnt->even_fields_captured;
2078                 mtr->odd_fields_captured = cnt->odd_fields_captured;
2079                 break;
2080         case METEORGCOUNT:      /* get error counts */
2081                 cnt = (struct meteor_counts *) data;
2082                 cnt->fifo_errors = mtr->fifo_errors;
2083                 cnt->dma_errors = mtr->dma_errors;
2084                 cnt->frames_captured = mtr->frames_captured;
2085                 cnt->even_fields_captured = mtr->even_fields_captured;
2086                 cnt->odd_fields_captured = mtr->odd_fields_captured;
2087                 break;
2088         default:
2089                 printf("meteor%d: ioctl: invalid ioctl request\n", unit);
2090                 error = ENOTTY;
2091                 break;
2092         }
2093         return(error);
2094 }
2095
2096 int
2097 meteor_mmap(struct dev_mmap_args *ap)
2098 {
2099         cdev_t dev = ap->a_head.a_dev;
2100         int     unit;
2101         meteor_reg_t *mtr;
2102
2103         unit = UNIT(minor(dev));
2104         if (unit >= NMETEOR)            /* at this point could this happen? */
2105                 return(-1);
2106
2107         mtr = &(meteor[unit]);
2108
2109
2110         if (ap->a_nprot & PROT_EXEC)
2111                 return -1;
2112
2113         if (ap->a_offset >= mtr->alloc_pages * PAGE_SIZE)
2114                 return -1;
2115
2116         return i386_btop(vtophys(mtr->bigbuf) + ap->a_offset);
2117 }