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