File:  [DragonFly] / src / sys / dev / video / meteor / meteor.c
Revision 1.13: download - view: text, annotated - select for diffs
Wed May 19 22:52:54 2004 UTC (10 years, 4 months ago) by dillon
Branches: MAIN
CVS tags: HEAD, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Device layer rollup commit.

* cdevsw_add() is now required.  cdevsw_add() and cdevsw_remove() may specify
  a mask/match indicating the range of supported minor numbers.  Multiple
  cdevsw_add()'s using the same major number, but distinctly different
  ranges, may be issued.  All devices that failed to call cdevsw_add() before
  now do.

* cdevsw_remove() now automatically marks all devices within its supported
  range as being destroyed.

* vnode->v_rdev is no longer resolved when the vnode is created.  Instead,
  only v_udev (a newly added field) is resolved.  v_rdev is resolved when
  the vnode is opened and cleared on the last close.

* A great deal of code was making rather dubious assumptions with regards
  to the validity of devices associated with vnodes, primarily due to
  the persistence of a device structure due to being indexed by (major, minor)
  instead of by (cdevsw, major, minor).  In particular, if you run a program
  which connects to a USB device and then you pull the USB device and plug
  it back in, the vnode subsystem will continue to believe that the device
  is open when, in fact, it isn't (because it was destroyed and recreated).

  In particular, note that all the VFS mount procedures now check devices
  via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
  is NULL prior to the first open.

* The disk layer's device interaction has been rewritten.  The disk layer
  (i.e. the slice and disklabel management layer) no longer overloads
  its data onto the device structure representing the underlying physical
  disk.  Instead, the disk layer uses the new cdevsw_add() functionality
  to register its own cdevsw using the underlying device's major number,
  and simply does NOT register the underlying device's cdevsw.  No
  confusion is created because the device hash is now based on
  (cdevsw,major,minor) rather then (major,minor).

  NOTE: This also means that underlying raw disk devices may use the entire
  device minor number instead of having to reserve the bits used by the disk
  layer, and also means that can we (theoretically) stack a fully
  disklabel-supported 'disk' on top of any block device.

* The new reference counting scheme prevents this by associating a device
  with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
  is removed.  Additionally, all udev2dev() lookups run through the cdevsw
  mask/match and only successfully find devices still associated with an
  active cdevsw.

* Major work on MFS:  MFS no longer shortcuts vnode and device creation.  It
  now creates a real vnode and a real device and implements real open and
  close VOPs.  Additionally, due to the disk layer changes, MFS is no longer
  limited to 255 mounts.  The new limit is 16 million.  Since MFS creates a
  real device node, mount_mfs will now create a real /dev/mfs<PID> device
  that can be read from userland (e.g. so you can dump an MFS filesystem).

* BUF AND DEVICE STRATEGY changes.  The struct buf contains a b_dev field.
  In order to properly handle stacked devices we now require that the b_dev
  field be initialized before the device strategy routine is called.  This
  required some additional work in various VFS implementations.  To enforce
  this requirement, biodone() now sets b_dev to NODEV.  The new disk layer
  will adjust b_dev before forwarding a request to the actual physical
  device.

* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.

Testing by: lots of people, but David Rhodus found the most aggregious bugs.

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