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