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