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