bktr_os.c revision 93023
151694Sroger/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 93023 2002-03-23 15:49:15Z nsouch $ */
251694Sroger
351694Sroger/*
451694Sroger * This is part of the Driver for Video Capture Cards (Frame grabbers)
551694Sroger * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
651694Sroger * chipset.
751694Sroger * Copyright Roger Hardiman and Amancio Hasty.
851694Sroger *
951694Sroger * bktr_os : This has all the Operating System dependant code,
1051694Sroger *             probe/attach and open/close/ioctl/read/mmap
1151694Sroger *             memory allocation
1251694Sroger *             PCI bus interfacing
1351694Sroger *
1451694Sroger *
1551694Sroger */
1651694Sroger
1751694Sroger/*
1851694Sroger * 1. Redistributions of source code must retain the
1951694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
2051694Sroger * All rights reserved.
2151694Sroger *
2251694Sroger * Redistribution and use in source and binary forms, with or without
2351694Sroger * modification, are permitted provided that the following conditions
2451694Sroger * are met:
2551694Sroger * 1. Redistributions of source code must retain the above copyright
2651694Sroger *    notice, this list of conditions and the following disclaimer.
2751694Sroger * 2. Redistributions in binary form must reproduce the above copyright
2851694Sroger *    notice, this list of conditions and the following disclaimer in the
2951694Sroger *    documentation and/or other materials provided with the distribution.
3051694Sroger * 3. All advertising materials mentioning features or use of this software
3151694Sroger *    must display the following acknowledgement:
3251694Sroger *	This product includes software developed by Amancio Hasty and
3351694Sroger *      Roger Hardiman
3451694Sroger * 4. The name of the author may not be used to endorse or promote products
3551694Sroger *    derived from this software without specific prior written permission.
3651694Sroger *
3751694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
3851694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
3951694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
4051694Sroger * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
4151694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
4251694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
4351694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4451694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4551694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
4651694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4751694Sroger * POSSIBILITY OF SUCH DAMAGE.
4851694Sroger */
4951694Sroger
5051694Sroger
5151694Sroger#ifdef __FreeBSD__
5251694Sroger#include "bktr.h"
5351694Sroger#endif /* __FreeBSD__ */
5451694Sroger
5559014Sroger#include "opt_bktr.h"		/* include any kernel config options */
5651694Sroger
5751694Sroger#define FIFO_RISC_DISABLED      0
5851694Sroger#define ALL_INTS_DISABLED       0
5951694Sroger
6062214Sroger
6162214Sroger/*******************/
6262214Sroger/* *** FreeBSD *** */
6362214Sroger/*******************/
6462214Sroger#ifdef __FreeBSD__
6562214Sroger
6651694Sroger#include <sys/param.h>
6751694Sroger#include <sys/systm.h>
6851694Sroger#include <sys/conf.h>
6951694Sroger#include <sys/uio.h>
7051694Sroger#include <sys/kernel.h>
7151694Sroger#include <sys/signalvar.h>
7251694Sroger#include <sys/mman.h>
7351694Sroger#include <sys/poll.h>
7470834Swollman#if __FreeBSD_version >= 500014
7570834Swollman#include <sys/selinfo.h>
7670834Swollman#else
7751694Sroger#include <sys/select.h>
7870834Swollman#endif
7951694Sroger#include <sys/vnode.h>
8051694Sroger
8151694Sroger#include <vm/vm.h>
8251694Sroger#include <vm/vm_kern.h>
8351694Sroger#include <vm/pmap.h>
8451694Sroger#include <vm/vm_extern.h>
8551694Sroger
8693023Snsouch#if (__FreeBSD_version >=400000)
8751694Sroger#include <sys/bus.h>		/* used by smbus and newbus */
8851694Sroger#endif
8951694Sroger
9059014Sroger#if (__FreeBSD_version >=300000)
9159014Sroger#include <machine/bus_memio.h>	/* used by bus space */
9259014Sroger#include <machine/bus.h>	/* used by bus space and newbus */
9359014Sroger#include <sys/bus.h>
9459014Sroger#endif
9559014Sroger
9651694Sroger#if (__FreeBSD_version >=400000)
9751694Sroger#include <sys/rman.h>		/* used by newbus */
9851694Sroger#include <machine/resource.h>	/* used by newbus */
9951694Sroger#endif
10051694Sroger
10167306Sroger#if (__FreeBSD_version < 500000)
10267306Sroger#include <machine/clock.h>              /* for DELAY */
10367306Sroger#endif
10459014Sroger
10551694Sroger#include <pci/pcivar.h>
10651694Sroger#include <pci/pcireg.h>
10751694Sroger
10851694Sroger#include <sys/sysctl.h>
10951694Srogerint bt848_card = -1;
11051694Srogerint bt848_tuner = -1;
11151694Srogerint bt848_reverse_mute = -1;
11251694Srogerint bt848_format = -1;
11359014Srogerint bt848_slow_msp_audio = -1;
11451694Sroger
11551694SrogerSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
11651694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
11751694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
11851694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
11951694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
12059014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
12151694Sroger
12251694Sroger#if (__FreeBSD__ == 2)
12351694Sroger#define PCIR_REVID     PCI_CLASS_REG
12451694Sroger#endif
12551694Sroger
12662214Sroger#endif /* end freebsd section */
12751694Sroger
12862214Sroger
12962214Sroger
13051694Sroger/****************/
13151694Sroger/* *** BSDI *** */
13251694Sroger/****************/
13351694Sroger#ifdef __bsdi__
13451694Sroger#endif /* __bsdi__ */
13551694Sroger
13651694Sroger
13751694Sroger/**************************/
13851694Sroger/* *** OpenBSD/NetBSD *** */
13951694Sroger/**************************/
14051694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__)
14162214Sroger
14262214Sroger#include <sys/param.h>
14362214Sroger#include <sys/systm.h>
14462214Sroger#include <sys/conf.h>
14562214Sroger#include <sys/uio.h>
14662214Sroger#include <sys/kernel.h>
14762214Sroger#include <sys/signalvar.h>
14862214Sroger#include <sys/mman.h>
14962214Sroger#include <sys/poll.h>
15062214Sroger#include <sys/select.h>
15162214Sroger#include <sys/vnode.h>
15262214Sroger
15362214Sroger#include <vm/vm.h>
15462214Sroger
15562214Sroger#ifndef __NetBSD__
15662214Sroger#include <vm/vm_kern.h>
15762214Sroger#include <vm/pmap.h>
15862214Sroger#include <vm/vm_extern.h>
15962214Sroger#endif
16062214Sroger
16159014Sroger#include <sys/device.h>
16259014Sroger#include <dev/pci/pcivar.h>
16359014Sroger#include <dev/pci/pcireg.h>
16459014Sroger#include <dev/pci/pcidevs.h>
16559014Sroger
16659014Sroger#define BKTR_DEBUG
16759014Sroger#ifdef BKTR_DEBUG
16859014Srogerint bktr_debug = 0;
16959014Sroger#define DPR(x)	(bktr_debug ? printf x : 0)
17059014Sroger#else
17159014Sroger#define DPR(x)
17259014Sroger#endif
17351694Sroger#endif /* __NetBSD__ || __OpenBSD__ */
17451694Sroger
17551694Sroger
17662214Sroger#ifdef __NetBSD__
17762214Sroger#include <dev/ic/bt8xx.h>	/* NetBSD location for .h files */
17862214Sroger#include <dev/pci/bktr/bktr_reg.h>
17962214Sroger#include <dev/pci/bktr/bktr_tuner.h>
18062214Sroger#include <dev/pci/bktr/bktr_card.h>
18162214Sroger#include <dev/pci/bktr/bktr_audio.h>
18262214Sroger#include <dev/pci/bktr/bktr_core.h>
18362214Sroger#include <dev/pci/bktr/bktr_os.h>
18462214Sroger#else					/* Traditional location for .h files */
18562214Sroger#include <machine/ioctl_meteor.h>
18662214Sroger#include <machine/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
18762214Sroger#include <dev/bktr/bktr_reg.h>
18862214Sroger#include <dev/bktr/bktr_tuner.h>
18962214Sroger#include <dev/bktr/bktr_card.h>
19062214Sroger#include <dev/bktr/bktr_audio.h>
19162214Sroger#include <dev/bktr/bktr_core.h>
19262214Sroger#include <dev/bktr/bktr_os.h>
19393023Snsouch
19465692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS)
19565392Speter#include <dev/bktr/bktr_i2c.h>
19693023Snsouch
19793023Snsouch#include "iicbb_if.h"
19893023Snsouch#include "smbus_if.h"
19962214Sroger#endif
20065392Speter#endif
20151694Sroger
20262214Sroger
20351694Sroger/****************************/
20451694Sroger/* *** FreeBSD 4.x code *** */
20551694Sroger/****************************/
20651694Sroger#if (__FreeBSD_version >= 400000)
20751694Sroger
20851694Srogerstatic int	bktr_probe( device_t dev );
20951694Srogerstatic int	bktr_attach( device_t dev );
21051694Srogerstatic int	bktr_detach( device_t dev );
21151694Srogerstatic int	bktr_shutdown( device_t dev );
21251694Srogerstatic void	bktr_intr(void *arg) { common_bktr_intr(arg); }
21351694Sroger
21451694Srogerstatic device_method_t bktr_methods[] = {
21551694Sroger	/* Device interface */
21651694Sroger	DEVMETHOD(device_probe,         bktr_probe),
21751694Sroger	DEVMETHOD(device_attach,        bktr_attach),
21851694Sroger	DEVMETHOD(device_detach,        bktr_detach),
21951694Sroger	DEVMETHOD(device_shutdown,      bktr_shutdown),
22051694Sroger
22193023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS)
22293023Snsouch	/* iicbb interface */
22393023Snsouch	DEVMETHOD(iicbb_callback,	bti2c_iic_callback),
22493023Snsouch	DEVMETHOD(iicbb_setsda,		bti2c_iic_setsda),
22593023Snsouch	DEVMETHOD(iicbb_setscl,		bti2c_iic_setscl),
22693023Snsouch	DEVMETHOD(iicbb_getsda,		bti2c_iic_getsda),
22793023Snsouch	DEVMETHOD(iicbb_getscl,		bti2c_iic_getscl),
22893023Snsouch	DEVMETHOD(iicbb_reset,		bti2c_iic_reset),
22993023Snsouch
23093023Snsouch	/* smbus interface */
23193023Snsouch	DEVMETHOD(smbus_callback,	bti2c_smb_callback),
23293023Snsouch	DEVMETHOD(smbus_writeb,		bti2c_smb_writeb),
23393023Snsouch	DEVMETHOD(smbus_writew,		bti2c_smb_writew),
23493023Snsouch	DEVMETHOD(smbus_readb,		bti2c_smb_readb),
23593023Snsouch#endif
23693023Snsouch
23751694Sroger	{ 0, 0 }
23851694Sroger};
23951694Sroger
24051694Srogerstatic driver_t bktr_driver = {
24151694Sroger	"bktr",
24251694Sroger	bktr_methods,
24351694Sroger	sizeof(struct bktr_softc),
24451694Sroger};
24551694Sroger
24651694Srogerstatic devclass_t bktr_devclass;
24751694Sroger
24851694Srogerstatic	d_open_t	bktr_open;
24951694Srogerstatic	d_close_t	bktr_close;
25051694Srogerstatic	d_read_t	bktr_read;
25151694Srogerstatic	d_write_t	bktr_write;
25251694Srogerstatic	d_ioctl_t	bktr_ioctl;
25351694Srogerstatic	d_mmap_t	bktr_mmap;
25451694Srogerstatic	d_poll_t	bktr_poll;
25551694Sroger
25651694Sroger#define CDEV_MAJOR 92
25751694Srogerstatic struct cdevsw bktr_cdevsw = {
25851694Sroger	/* open */	bktr_open,
25951694Sroger	/* close */	bktr_close,
26051694Sroger	/* read */	bktr_read,
26151694Sroger	/* write */	bktr_write,
26251694Sroger	/* ioctl */	bktr_ioctl,
26351694Sroger	/* poll */	bktr_poll,
26451694Sroger	/* mmap */	bktr_mmap,
26551694Sroger	/* strategy */	nostrategy,
26651694Sroger	/* name */	"bktr",
26751694Sroger	/* maj */	CDEV_MAJOR,
26851694Sroger	/* dump */	nodump,
26951694Sroger	/* psize */	nopsize,
27051694Sroger	/* flags */	0,
27151694Sroger};
27251694Sroger
27352995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0);
27467306Sroger#if (__FreeBSD_version > 410000)
27565728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1);
27665728SrogerMODULE_VERSION(bktr, 1);
27767306Sroger#endif
27851694Sroger
27951694Sroger
28051694Sroger/*
28151694Sroger * the boot time probe routine.
28251694Sroger */
28351694Srogerstatic int
28451694Srogerbktr_probe( device_t dev )
28551694Sroger{
28651694Sroger	unsigned int type = pci_get_devid(dev);
28751694Sroger        unsigned int rev  = pci_get_revid(dev);
28851694Sroger
28967306Sroger	if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
29067306Sroger	{
29167306Sroger		switch (PCI_PRODUCT(type)) {
29267306Sroger		case PCI_PRODUCT_BROOKTREE_BT848:
29367306Sroger			if (rev == 0x12)
29467306Sroger				device_set_desc(dev, "BrookTree 848A");
29567306Sroger			else
29667306Sroger				device_set_desc(dev, "BrookTree 848");
29767306Sroger			return 0;
29867306Sroger		case PCI_PRODUCT_BROOKTREE_BT849:
29967306Sroger			device_set_desc(dev, "BrookTree 849A");
30067306Sroger			return 0;
30167306Sroger		case PCI_PRODUCT_BROOKTREE_BT878:
30267306Sroger			device_set_desc(dev, "BrookTree 878");
30367306Sroger			return 0;
30467306Sroger		case PCI_PRODUCT_BROOKTREE_BT879:
30567306Sroger			device_set_desc(dev, "BrookTree 879");
30667306Sroger			return 0;
30767306Sroger		}
30851694Sroger	};
30951694Sroger
31051694Sroger        return ENXIO;
31151694Sroger}
31251694Sroger
31351694Sroger
31451694Sroger/*
31551694Sroger * the attach routine.
31651694Sroger */
31751694Srogerstatic int
31851694Srogerbktr_attach( device_t dev )
31951694Sroger{
32051694Sroger	u_long		latency;
32151694Sroger	u_long		fun;
32251694Sroger	u_long		val;
32351694Sroger	unsigned int	rev;
32451694Sroger	unsigned int	unit;
32551694Sroger	int		error = 0;
32651694Sroger#ifdef BROOKTREE_IRQ
32751694Sroger	u_long		old_irq, new_irq;
32851694Sroger#endif
32951694Sroger
33051694Sroger        struct bktr_softc *bktr = device_get_softc(dev);
33151694Sroger
33251694Sroger	unit = device_get_unit(dev);
33351694Sroger
33462112Sroger	/* build the device name for bktr_name() */
33562112Sroger	snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
33662112Sroger
33751694Sroger	/*
33851694Sroger	 * Enable bus mastering and Memory Mapped device
33951694Sroger	 */
34051694Sroger	val = pci_read_config(dev, PCIR_COMMAND, 4);
34151694Sroger	val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
34251694Sroger	pci_write_config(dev, PCIR_COMMAND, val, 4);
34351694Sroger
34451694Sroger	/*
34551694Sroger	 * Map control/status registers.
34651694Sroger	 */
34765049Sroger	bktr->mem_rid = PCIR_MAPS;
34865049Sroger	bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid,
34965049Sroger					0, ~0, 1, RF_ACTIVE);
35051694Sroger
35165049Sroger
35251694Sroger	if (!bktr->res_mem) {
35351694Sroger		device_printf(dev, "could not map memory\n");
35451694Sroger		error = ENXIO;
35551694Sroger		goto fail;
35651694Sroger	}
35759014Sroger	bktr->memt = rman_get_bustag(bktr->res_mem);
35859014Sroger	bktr->memh = rman_get_bushandle(bktr->res_mem);
35951694Sroger
36059014Sroger
36151694Sroger	/*
36251694Sroger	 * Disable the brooktree device
36351694Sroger	 */
36459014Sroger	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
36559014Sroger	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
36651694Sroger
36751694Sroger
36851694Sroger#ifdef BROOKTREE_IRQ		/* from the configuration file */
36951694Sroger	old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
37051694Sroger	pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
37151694Sroger	new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
37251694Sroger	printf("bktr%d: attach: irq changed from %d to %d\n",
37351694Sroger		unit, (old_irq & 0xff), (new_irq & 0xff));
37451694Sroger#endif
37551694Sroger
37651694Sroger	/*
37751694Sroger	 * Allocate our interrupt.
37851694Sroger	 */
37965049Sroger	bktr->irq_rid = 0;
38065049Sroger	bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid,
38165049Sroger				0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
38251694Sroger	if (bktr->res_irq == NULL) {
38351694Sroger		device_printf(dev, "could not map interrupt\n");
38451694Sroger		error = ENXIO;
38551694Sroger		goto fail;
38651694Sroger	}
38751694Sroger
38859250Sroger	error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY,
38951694Sroger                               bktr_intr, bktr, &bktr->res_ih);
39051694Sroger	if (error) {
39151694Sroger		device_printf(dev, "could not setup irq\n");
39251694Sroger		goto fail;
39351694Sroger
39451694Sroger	}
39551694Sroger
39651694Sroger
39751694Sroger	/* Update the Device Control Register */
39851694Sroger	/* on Bt878 and Bt879 cards           */
39951694Sroger	fun = pci_read_config( dev, 0x40, 2);
40051694Sroger        fun = fun | 1;	/* Enable writes to the sub-system vendor ID */
40151694Sroger
40251694Sroger#if defined( BKTR_430_FX_MODE )
40351694Sroger	if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
40451694Sroger        fun = fun | 2;	/* Enable Intel 430 FX compatibility mode */
40551694Sroger#endif
40651694Sroger
40751694Sroger#if defined( BKTR_SIS_VIA_MODE )
40851694Sroger	if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
40951694Sroger        fun = fun | 4;	/* Enable SiS/VIA compatibility mode (usefull for
41051694Sroger                           OPTi chipset motherboards too */
41151694Sroger#endif
41251694Sroger	pci_write_config(dev, 0x40, fun, 2);
41351694Sroger
41465692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS)
41593023Snsouch	if (bt848_i2c_attach(dev))
41651694Sroger		printf("bktr%d: i2c_attach: can't attach\n", unit);
41751694Sroger#endif
41851694Sroger
41951694Sroger/*
42051694Sroger * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
42151694Sroger * you have more than four, then 16 would probably be a better value.
42251694Sroger */
42351694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE
42451694Sroger#define BROOKTREE_DEF_LATENCY_VALUE	10
42551694Sroger#endif
42651694Sroger	latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4);
42751694Sroger	latency = (latency >> 8) & 0xff;
42851694Sroger	if ( bootverbose ) {
42951694Sroger		if (latency)
43051694Sroger			printf("brooktree%d: PCI bus latency is", unit);
43151694Sroger		else
43251694Sroger			printf("brooktree%d: PCI bus latency was 0 changing to",
43351694Sroger				unit);
43451694Sroger	}
43551694Sroger	if ( !latency ) {
43651694Sroger		latency = BROOKTREE_DEF_LATENCY_VALUE;
43751694Sroger		pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4);
43851694Sroger	}
43951694Sroger	if ( bootverbose ) {
44051694Sroger		printf(" %d.\n", (int) latency);
44151694Sroger	}
44251694Sroger
44351694Sroger	/* read the pci device id and revision id */
44451694Sroger	fun = pci_get_devid(dev);
44551694Sroger        rev = pci_get_revid(dev);
44651694Sroger
44751694Sroger	/* call the common attach code */
44851694Sroger	common_bktr_attach( bktr, unit, fun, rev );
44951694Sroger
45067306Sroger	/* make the device entries */
45167306Sroger	bktr->bktrdev = make_dev(&bktr_cdevsw, unit,
45267306Sroger				0, 0, 0444, "bktr%d",  unit);
45367306Sroger	bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16,
45467306Sroger				0, 0, 0444, "tuner%d", unit);
45567306Sroger	bktr->vbidev  = make_dev(&bktr_cdevsw, unit+32,
45667306Sroger				0, 0, 0444, "vbi%d"  , unit);
45751694Sroger
45867306Sroger
45967306Sroger	/* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */
46067306Sroger	/* alias entries to /dev/bktr /dev/tuner and /dev/vbi */
46167306Sroger#if (__FreeBSD_version >=500000)
46267306Sroger	if (unit == 0) {
46367306Sroger		bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev,  "bktr");
46467306Sroger		bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner");
46567306Sroger		bktr->vbidev_alias  = make_dev_alias(bktr->vbidev,   "vbi");
46667306Sroger	}
46767306Sroger#endif
46867306Sroger
46951694Sroger	return 0;
47051694Sroger
47151694Srogerfail:
47265049Sroger	if (bktr->res_irq)
47365049Sroger		bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
47465049Sroger	if (bktr->res_mem)
47565049Sroger		bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem);
47651694Sroger	return error;
47751694Sroger
47851694Sroger}
47951694Sroger
48051694Sroger/*
48151694Sroger * the detach routine.
48251694Sroger */
48351694Srogerstatic int
48451694Srogerbktr_detach( device_t dev )
48551694Sroger{
48667366Sroger	unsigned int	unit;
48767366Sroger
48851694Sroger	struct bktr_softc *bktr = device_get_softc(dev);
48951694Sroger
49067366Sroger	unit = device_get_unit(dev);
49167366Sroger
49251694Sroger	/* Disable the brooktree device */
49359014Sroger	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
49459014Sroger	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
49551694Sroger
49693023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS)
49793023Snsouch	if (bt848_i2c_detach(dev))
49893023Snsouch		printf("bktr%d: i2c_attach: can't attach\n", unit);
49993023Snsouch#endif
50093023Snsouch
50167306Sroger	/* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */
50267306Sroger	/* The memory is retained by the bktr_mem module so we can unload and */
50367306Sroger	/* then reload the main bktr driver module */
50451694Sroger
50567306Sroger	/* Unregister the /dev/bktrN, tunerN and vbiN devices */
50667306Sroger	destroy_dev(bktr->vbidev);
50767306Sroger	destroy_dev(bktr->tunerdev);
50867306Sroger	destroy_dev(bktr->bktrdev);
50967306Sroger
51067306Sroger	/* If this is unit 0, then destroy the alias entries too */
51167306Sroger#if (__FreeBSD_version >=500000)
51267306Sroger	if (unit == 0) {
51367306Sroger	    destroy_dev(bktr->vbidev_alias);
51467306Sroger	    destroy_dev(bktr->tunerdev_alias);
51567306Sroger	    destroy_dev(bktr->bktrdev_alias);
51667306Sroger	}
51767306Sroger#endif
51867306Sroger
51951694Sroger	/*
52051694Sroger	 * Deallocate resources.
52151694Sroger	 */
52251694Sroger	bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
52365049Sroger	bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
52465049Sroger	bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
52565049Sroger
52651694Sroger	return 0;
52751694Sroger}
52851694Sroger
52951694Sroger/*
53051694Sroger * the shutdown routine.
53151694Sroger */
53251694Srogerstatic int
53351694Srogerbktr_shutdown( device_t dev )
53451694Sroger{
53551694Sroger	struct bktr_softc *bktr = device_get_softc(dev);
53651694Sroger
53751694Sroger	/* Disable the brooktree device */
53859014Sroger	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
53959014Sroger	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
54051694Sroger
54151694Sroger	return 0;
54251694Sroger}
54351694Sroger
54451694Sroger
54551694Sroger/*
54651694Sroger * Special Memory Allocation
54751694Sroger */
54851694Srogervm_offset_t
54951694Srogerget_bktr_mem( int unit, unsigned size )
55051694Sroger{
55151694Sroger	vm_offset_t	addr = 0;
55251694Sroger
55351694Sroger	addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
55451694Sroger	if (addr == 0)
55551694Sroger		addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
55651694Sroger	if (addr == 0) {
55751694Sroger		printf("bktr%d: Unable to allocate %d bytes of memory.\n",
55851694Sroger			unit, size);
55951694Sroger	}
56051694Sroger
56151694Sroger	return( addr );
56251694Sroger}
56351694Sroger
56451694Sroger
56551694Sroger/*---------------------------------------------------------
56651694Sroger**
56751694Sroger**	BrookTree 848 character device driver routines
56851694Sroger**
56951694Sroger**---------------------------------------------------------
57051694Sroger*/
57151694Sroger
57251694Sroger#define VIDEO_DEV	0x00
57351694Sroger#define TUNER_DEV	0x01
57451694Sroger#define VBI_DEV		0x02
57551694Sroger
57651694Sroger#define UNIT(x)		((x) & 0x0f)
57751694Sroger#define FUNCTION(x)	(x >> 4)
57851694Sroger
57951694Sroger/*
58051694Sroger *
58151694Sroger */
58251694Srogerint
58383366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td )
58451694Sroger{
58551694Sroger	bktr_ptr_t	bktr;
58651694Sroger	int		unit;
58751694Sroger	int		result;
58851694Sroger
58951694Sroger	unit = UNIT( minor(dev) );
59051694Sroger
59151694Sroger	/* Get the device data */
59251694Sroger	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
59351694Sroger	if (bktr == NULL) {
59451694Sroger		/* the device is no longer valid/functioning */
59551694Sroger		return (ENXIO);
59651694Sroger	}
59751694Sroger
59851694Sroger	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
59951694Sroger		return( ENXIO );
60051694Sroger
60151694Sroger	/* Record that the device is now busy */
60251694Sroger	device_busy(devclass_get_device(bktr_devclass, unit));
60351694Sroger
60451694Sroger
60551694Sroger	if (bt848_card != -1) {
60651694Sroger	  if ((bt848_card >> 8   == unit ) &&
60751694Sroger	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
60851694Sroger	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
60951694Sroger	      bktr->bt848_card = (bt848_card & 0xff);
61051694Sroger	      probeCard(bktr, FALSE, unit);
61151694Sroger	    }
61251694Sroger	  }
61351694Sroger	}
61451694Sroger
61551694Sroger	if (bt848_tuner != -1) {
61651694Sroger	  if ((bt848_tuner >> 8   == unit ) &&
61751694Sroger	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
61851694Sroger	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
61951694Sroger	      bktr->bt848_tuner = (bt848_tuner & 0xff);
62051694Sroger	      probeCard(bktr, FALSE, unit);
62151694Sroger	    }
62251694Sroger	  }
62351694Sroger	}
62451694Sroger
62551694Sroger	if (bt848_reverse_mute != -1) {
62659014Sroger	  if ((bt848_reverse_mute >> 8)   == unit ) {
62751694Sroger	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
62851694Sroger	  }
62951694Sroger	}
63051694Sroger
63159014Sroger	if (bt848_slow_msp_audio != -1) {
63259014Sroger	  if ((bt848_slow_msp_audio >> 8) == unit ) {
63359014Sroger	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
63459014Sroger	  }
63559014Sroger	}
63659014Sroger
63751694Sroger	switch ( FUNCTION( minor(dev) ) ) {
63851694Sroger	case VIDEO_DEV:
63951694Sroger		result = video_open( bktr );
64051694Sroger		break;
64151694Sroger	case TUNER_DEV:
64251694Sroger		result = tuner_open( bktr );
64351694Sroger		break;
64451694Sroger	case VBI_DEV:
64551694Sroger		result = vbi_open( bktr );
64651694Sroger		break;
64751694Sroger	default:
64851694Sroger		result = ENXIO;
64951694Sroger		break;
65051694Sroger	}
65151694Sroger
65251694Sroger	/* If there was an error opening the device, undo the busy status */
65351694Sroger	if (result != 0)
65451694Sroger		device_unbusy(devclass_get_device(bktr_devclass, unit));
65551694Sroger	return( result );
65651694Sroger}
65751694Sroger
65851694Sroger
65951694Sroger/*
66051694Sroger *
66151694Sroger */
66251694Srogerint
66383366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td )
66451694Sroger{
66551694Sroger	bktr_ptr_t	bktr;
66651694Sroger	int		unit;
66751694Sroger	int		result;
66851694Sroger
66951694Sroger	unit = UNIT( minor(dev) );
67051694Sroger
67151694Sroger	/* Get the device data */
67251694Sroger	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
67351694Sroger	if (bktr == NULL) {
67451694Sroger		/* the device is no longer valid/functioning */
67551694Sroger		return (ENXIO);
67651694Sroger	}
67751694Sroger
67851694Sroger	switch ( FUNCTION( minor(dev) ) ) {
67951694Sroger	case VIDEO_DEV:
68051694Sroger		result = video_close( bktr );
68151694Sroger		break;
68251694Sroger	case TUNER_DEV:
68351694Sroger		result = tuner_close( bktr );
68451694Sroger		break;
68551694Sroger	case VBI_DEV:
68651694Sroger		result = vbi_close( bktr );
68751694Sroger		break;
68851694Sroger	default:
68951694Sroger		return (ENXIO);
69051694Sroger		break;
69151694Sroger	}
69251694Sroger
69351694Sroger	device_unbusy(devclass_get_device(bktr_devclass, unit));
69451694Sroger	return( result );
69551694Sroger}
69651694Sroger
69751694Sroger
69851694Sroger/*
69951694Sroger *
70051694Sroger */
70151694Srogerint
70251694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag )
70351694Sroger{
70451694Sroger	bktr_ptr_t	bktr;
70551694Sroger	int		unit;
70651694Sroger
70751694Sroger	unit = UNIT(minor(dev));
70851694Sroger
70951694Sroger	/* Get the device data */
71051694Sroger	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
71151694Sroger	if (bktr == NULL) {
71251694Sroger		/* the device is no longer valid/functioning */
71351694Sroger		return (ENXIO);
71451694Sroger	}
71551694Sroger
71651694Sroger	switch ( FUNCTION( minor(dev) ) ) {
71751694Sroger	case VIDEO_DEV:
71851694Sroger		return( video_read( bktr, unit, dev, uio ) );
71951694Sroger	case VBI_DEV:
72051694Sroger		return( vbi_read( bktr, uio, ioflag ) );
72151694Sroger	}
72251694Sroger        return( ENXIO );
72351694Sroger}
72451694Sroger
72551694Sroger
72651694Sroger/*
72751694Sroger *
72851694Sroger */
72951694Srogerint
73051694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag )
73151694Sroger{
73251694Sroger	return( EINVAL ); /* XXX or ENXIO ? */
73351694Sroger}
73451694Sroger
73551694Sroger
73651694Sroger/*
73751694Sroger *
73851694Sroger */
73951694Srogerint
74083366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td )
74151694Sroger{
74251694Sroger	bktr_ptr_t	bktr;
74351694Sroger	int		unit;
74451694Sroger
74551694Sroger	unit = UNIT(minor(dev));
74651694Sroger
74751694Sroger	/* Get the device data */
74851694Sroger	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
74951694Sroger	if (bktr == NULL) {
75051694Sroger		/* the device is no longer valid/functioning */
75151694Sroger		return (ENXIO);
75251694Sroger	}
75351694Sroger
75451694Sroger	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
75551694Sroger		return( ENOMEM );
75651694Sroger
75751694Sroger	switch ( FUNCTION( minor(dev) ) ) {
75851694Sroger	case VIDEO_DEV:
75983366Sjulian		return( video_ioctl( bktr, unit, cmd, arg, td ) );
76051694Sroger	case TUNER_DEV:
76183366Sjulian		return( tuner_ioctl( bktr, unit, cmd, arg, td ) );
76251694Sroger	}
76351694Sroger
76451694Sroger	return( ENXIO );
76551694Sroger}
76651694Sroger
76751694Sroger
76851694Sroger/*
76951694Sroger *
77051694Sroger */
77151694Srogerint
77251694Srogerbktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
77351694Sroger{
77451694Sroger	int		unit;
77551694Sroger	bktr_ptr_t	bktr;
77651694Sroger
77751694Sroger	unit = UNIT(minor(dev));
77851694Sroger
77951694Sroger	if (FUNCTION(minor(dev)) > 0)	/* only allow mmap on /dev/bktr[n] */
78051694Sroger		return( -1 );
78151694Sroger
78251694Sroger	/* Get the device data */
78351694Sroger	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
78451694Sroger	if (bktr == NULL) {
78551694Sroger		/* the device is no longer valid/functioning */
78651694Sroger		return (ENXIO);
78751694Sroger	}
78851694Sroger
78951694Sroger	if (nprot & PROT_EXEC)
79051694Sroger		return( -1 );
79151694Sroger
79251694Sroger	if (offset < 0)
79351694Sroger		return( -1 );
79451694Sroger
79551694Sroger	if (offset >= bktr->alloc_pages * PAGE_SIZE)
79651694Sroger		return( -1 );
79751694Sroger
79859250Sroger	return( atop(vtophys(bktr->bigbuf) + offset) );
79951694Sroger}
80051694Sroger
80183366Sjulianint bktr_poll( dev_t dev, int events, struct thread *td)
80251694Sroger{
80351694Sroger	int		unit;
80451694Sroger	bktr_ptr_t	bktr;
80551694Sroger	int revents = 0;
80659277Sroger	DECLARE_INTR_MASK(s);
80751694Sroger
80851694Sroger	unit = UNIT(minor(dev));
80951694Sroger
81051694Sroger	/* Get the device data */
81151694Sroger	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
81251694Sroger	if (bktr == NULL) {
81351694Sroger		/* the device is no longer valid/functioning */
81451694Sroger		return (ENXIO);
81551694Sroger	}
81651694Sroger
81759277Sroger	DISABLE_INTR(s);
81851694Sroger
81951694Sroger	if (events & (POLLIN | POLLRDNORM)) {
82051694Sroger
82151694Sroger		switch ( FUNCTION( minor(dev) ) ) {
82251694Sroger		case VBI_DEV:
82351694Sroger			if(bktr->vbisize == 0)
82483366Sjulian				selrecord(td, &bktr->vbi_select);
82551694Sroger			else
82651694Sroger				revents |= events & (POLLIN | POLLRDNORM);
82751694Sroger			break;
82851694Sroger		}
82951694Sroger	}
83051694Sroger
83159250Sroger	ENABLE_INTR(s);
83251694Sroger
83351694Sroger	return (revents);
83451694Sroger}
83551694Sroger
83651694Sroger#endif		/* FreeBSD 4.x specific kernel interface routines */
83751694Sroger
83851694Sroger/**********************************/
83951694Sroger/* *** FreeBSD 2.2.x and 3.x  *** */
84051694Sroger/**********************************/
84151694Sroger
84251694Sroger#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3))
84351694Sroger
84451694Srogerstatic bktr_reg_t brooktree[ NBKTR ];
84551694Sroger
84651694Srogerstatic const char*	bktr_probe( pcici_t tag, pcidi_t type );
84751694Srogerstatic void		bktr_attach( pcici_t tag, int unit );
84851694Srogerstatic void		bktr_intr(void *arg) { common_bktr_intr(arg); }
84951694Sroger
85051694Srogerstatic u_long	bktr_count;
85151694Sroger
85251694Srogerstatic struct	pci_device bktr_device = {
85351694Sroger	"bktr",
85451694Sroger	bktr_probe,
85551694Sroger	bktr_attach,
85651694Sroger	&bktr_count
85751694Sroger};
85851694Sroger
85951694SrogerDATA_SET (pcidevice_set, bktr_device);
86051694Sroger
86151694Srogerstatic	d_open_t	bktr_open;
86251694Srogerstatic	d_close_t	bktr_close;
86351694Srogerstatic	d_read_t	bktr_read;
86451694Srogerstatic	d_write_t	bktr_write;
86551694Srogerstatic	d_ioctl_t	bktr_ioctl;
86651694Srogerstatic	d_mmap_t	bktr_mmap;
86751694Srogerstatic	d_poll_t	bktr_poll;
86851694Sroger
86951694Sroger#define CDEV_MAJOR 92
87051694Srogerstatic struct cdevsw bktr_cdevsw =
87151694Sroger{
87251694Sroger	bktr_open,	bktr_close,	bktr_read,	bktr_write,
87351694Sroger	bktr_ioctl,	nostop,		nullreset,	nodevtotty,
87451694Sroger	bktr_poll,	bktr_mmap,	NULL,		"bktr",
87551694Sroger	NULL,		-1
87651694Sroger};
87751694Sroger
87851694Sroger/*
87951694Sroger * the boot time probe routine.
88051694Sroger */
88151694Srogerstatic const char*
88251694Srogerbktr_probe( pcici_t tag, pcidi_t type )
88351694Sroger{
88451694Sroger        unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff;
88567306Sroger
88667306Sroger	if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
88767306Sroger	{
88867306Sroger		switch (PCI_PRODUCT(type)) {
88967306Sroger		case PCI_PRODUCT_BROOKTREE_BT848:
89067306Sroger			if (rev == 0x12) return("BrookTree 848A");
89167306Sroger			else             return("BrookTree 848");
89267306Sroger		case PCI_PRODUCT_BROOKTREE_BT849:
89367306Sroger			return("BrookTree 849A");
89467306Sroger		case PCI_PRODUCT_BROOKTREE_BT878:
89567306Sroger			return("BrookTree 878");
89667306Sroger		case PCI_PRODUCT_BROOKTREE_BT879:
89767306Sroger			return("BrookTree 879");
89867306Sroger		}
89951694Sroger	};
90051694Sroger
90151694Sroger	return ((char *)0);
90251694Sroger}
90351694Sroger
90451694Sroger/*
90551694Sroger * the attach routine.
90651694Sroger */
90751694Srogerstatic	void
90851694Srogerbktr_attach( pcici_t tag, int unit )
90951694Sroger{
91051694Sroger	bktr_ptr_t	bktr;
91151694Sroger	u_long		latency;
91251694Sroger	u_long		fun;
91351694Sroger	unsigned int	rev;
91459014Sroger	unsigned long	base;
91551694Sroger#ifdef BROOKTREE_IRQ
91651694Sroger	u_long		old_irq, new_irq;
91751694Sroger#endif
91851694Sroger
91951694Sroger	bktr = &brooktree[unit];
92051694Sroger
92151694Sroger	if (unit >= NBKTR) {
92251694Sroger		printf("brooktree%d: attach: only %d units configured.\n",
92351694Sroger		        unit, NBKTR);
92451694Sroger		printf("brooktree%d: attach: invalid unit number.\n", unit);
92551694Sroger		return;
92651694Sroger	}
92751694Sroger
92862112Sroger	/* build the device name for bktr_name() */
92962112Sroger	snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
93062112Sroger
93151694Sroger	/* Enable Memory Mapping */
93251694Sroger	fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
93351694Sroger	pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2);
93451694Sroger
93551694Sroger	/* Enable Bus Mastering */
93651694Sroger	fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
93751694Sroger	pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4);
93851694Sroger
93951694Sroger	bktr->tag = tag;
94051694Sroger
94151694Sroger
94251694Sroger	/*
94351694Sroger	 * Map control/status registers
94451694Sroger	 */
94559014Sroger	pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base,
94651694Sroger		     &bktr->phys_base );
94759014Sroger#if (__FreeBSD_version >= 300000)
94859014Sroger	bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */
94959014Sroger	bktr->memh = (bus_space_handle_t)base; /* XXX functions here */
95059014Sroger#endif
95151694Sroger
95251694Sroger	/*
95351694Sroger	 * Disable the brooktree device
95451694Sroger	 */
95559014Sroger	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
95659014Sroger	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
95751694Sroger
95851694Sroger#ifdef BROOKTREE_IRQ		/* from the configuration file */
95951694Sroger	old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
96051694Sroger	pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
96151694Sroger	new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
96251694Sroger	printf("bktr%d: attach: irq changed from %d to %d\n",
96351694Sroger		unit, (old_irq & 0xff), (new_irq & 0xff));
96451694Sroger#endif
96551694Sroger
96651694Sroger	/*
96751694Sroger	 * setup the interrupt handling routine
96851694Sroger	 */
96959250Sroger	pci_map_int(tag, bktr_intr, (void*) bktr, &tty_imask);
97051694Sroger
97151694Sroger
97251694Sroger	/* Update the Device Control Register */
97351694Sroger	/* on Bt878 and Bt879 cards */
97451694Sroger	fun = pci_conf_read(tag, 0x40);
97551694Sroger        fun = fun | 1;	/* Enable writes to the sub-system vendor ID */
97651694Sroger
97751694Sroger#if defined( BKTR_430_FX_MODE )
97851694Sroger	if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
97951694Sroger        fun = fun | 2;	/* Enable Intel 430 FX compatibility mode */
98051694Sroger#endif
98151694Sroger
98251694Sroger#if defined( BKTR_SIS_VIA_MODE )
98351694Sroger	if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
98451694Sroger        fun = fun | 4;	/* Enable SiS/VIA compatibility mode (usefull for
98551694Sroger                           OPTi chipset motherboards too */
98651694Sroger#endif
98751694Sroger	pci_conf_write(tag, 0x40, fun);
98851694Sroger
98965692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS)
99093023Snsouch	if (bt848_i2c_attach(dev))
99151694Sroger		printf("bktr%d: i2c_attach: can't attach\n", unit);
99251694Sroger#endif
99351694Sroger
99451694Sroger/*
99551694Sroger * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
99651694Sroger * you have more than four, then 16 would probably be a better value.
99751694Sroger */
99851694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE
99951694Sroger#define BROOKTREE_DEF_LATENCY_VALUE	10
100051694Sroger#endif
100151694Sroger	latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
100251694Sroger	latency = (latency >> 8) & 0xff;
100351694Sroger	if ( bootverbose ) {
100451694Sroger		if (latency)
100551694Sroger			printf("brooktree%d: PCI bus latency is", unit);
100651694Sroger		else
100751694Sroger			printf("brooktree%d: PCI bus latency was 0 changing to",
100851694Sroger				unit);
100951694Sroger	}
101051694Sroger	if ( !latency ) {
101151694Sroger		latency = BROOKTREE_DEF_LATENCY_VALUE;
101251694Sroger		pci_conf_write(tag, PCI_LATENCY_TIMER,	latency<<8);
101351694Sroger	}
101451694Sroger	if ( bootverbose ) {
101551694Sroger		printf(" %d.\n", (int) latency);
101651694Sroger	}
101751694Sroger
101851694Sroger
101951694Sroger	/* read the pci device id and revision id */
102051694Sroger	fun = pci_conf_read(tag, PCI_ID_REG);
102151694Sroger        rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff;
102251694Sroger
102351694Sroger	/* call the common attach code */
102451694Sroger	common_bktr_attach( bktr, unit, fun, rev );
102551694Sroger
102651694Sroger}
102751694Sroger
102851694Sroger
102951694Sroger/*
103051694Sroger * Special Memory Allocation
103151694Sroger */
103251694Srogervm_offset_t
103351694Srogerget_bktr_mem( int unit, unsigned size )
103451694Sroger{
103551694Sroger	vm_offset_t	addr = 0;
103651694Sroger
103751694Sroger	addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24);
103851694Sroger	if (addr == 0)
103951694Sroger		addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff,
104051694Sroger								PAGE_SIZE);
104151694Sroger	if (addr == 0) {
104251694Sroger		printf("bktr%d: Unable to allocate %d bytes of memory.\n",
104351694Sroger			unit, size);
104451694Sroger	}
104551694Sroger
104651694Sroger	return( addr );
104751694Sroger}
104851694Sroger
104951694Sroger/*---------------------------------------------------------
105051694Sroger**
105151694Sroger**	BrookTree 848 character device driver routines
105251694Sroger**
105351694Sroger**---------------------------------------------------------
105451694Sroger*/
105551694Sroger
105651694Sroger
105751694Sroger#define VIDEO_DEV	0x00
105851694Sroger#define TUNER_DEV	0x01
105951694Sroger#define VBI_DEV		0x02
106051694Sroger
106151694Sroger#define UNIT(x)		((x) & 0x0f)
106251694Sroger#define FUNCTION(x)	((x >> 4) & 0x0f)
106351694Sroger
106451694Sroger
106551694Sroger/*
106651694Sroger *
106751694Sroger */
106851694Srogerint
106983366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td )
107051694Sroger{
107151694Sroger	bktr_ptr_t	bktr;
107251694Sroger	int		unit;
107351694Sroger
107451694Sroger	unit = UNIT( minor(dev) );
107551694Sroger	if (unit >= NBKTR)			/* unit out of range */
107651694Sroger		return( ENXIO );
107751694Sroger
107851694Sroger	bktr = &(brooktree[ unit ]);
107951694Sroger
108051694Sroger	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
108151694Sroger		return( ENXIO );
108251694Sroger
108351694Sroger
108451694Sroger	if (bt848_card != -1) {
108551694Sroger	  if ((bt848_card >> 8   == unit ) &&
108651694Sroger	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
108751694Sroger	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
108851694Sroger	      bktr->bt848_card = (bt848_card & 0xff);
108951694Sroger	      probeCard(bktr, FALSE, unit);
109051694Sroger	    }
109151694Sroger	  }
109251694Sroger	}
109351694Sroger
109451694Sroger	if (bt848_tuner != -1) {
109551694Sroger	  if ((bt848_tuner >> 8   == unit ) &&
109651694Sroger	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
109751694Sroger	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
109851694Sroger	      bktr->bt848_tuner = (bt848_tuner & 0xff);
109951694Sroger	      probeCard(bktr, FALSE, unit);
110051694Sroger	    }
110151694Sroger	  }
110251694Sroger	}
110351694Sroger
110451694Sroger	if (bt848_reverse_mute != -1) {
110559014Sroger	  if ((bt848_reverse_mute >> 8)   == unit ) {
110651694Sroger	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
110751694Sroger	  }
110851694Sroger	}
110951694Sroger
111059014Sroger	if (bt848_slow_msp_audio != -1) {
111159014Sroger	  if ((bt848_slow_msp_audio >> 8) == unit ) {
111259014Sroger	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
111359014Sroger	  }
111459014Sroger	}
111551694Sroger
111651694Sroger	switch ( FUNCTION( minor(dev) ) ) {
111751694Sroger	case VIDEO_DEV:
111851694Sroger		return( video_open( bktr ) );
111951694Sroger	case TUNER_DEV:
112051694Sroger		return( tuner_open( bktr ) );
112151694Sroger	case VBI_DEV:
112251694Sroger		return( vbi_open( bktr ) );
112351694Sroger	}
112451694Sroger	return( ENXIO );
112551694Sroger}
112651694Sroger
112751694Sroger
112851694Sroger/*
112951694Sroger *
113051694Sroger */
113151694Srogerint
113283366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td )
113351694Sroger{
113451694Sroger	bktr_ptr_t	bktr;
113551694Sroger	int		unit;
113651694Sroger
113751694Sroger	unit = UNIT( minor(dev) );
113851694Sroger	if (unit >= NBKTR)			/* unit out of range */
113951694Sroger		return( ENXIO );
114051694Sroger
114151694Sroger	bktr = &(brooktree[ unit ]);
114251694Sroger
114351694Sroger	switch ( FUNCTION( minor(dev) ) ) {
114451694Sroger	case VIDEO_DEV:
114551694Sroger		return( video_close( bktr ) );
114651694Sroger	case TUNER_DEV:
114751694Sroger		return( tuner_close( bktr ) );
114851694Sroger	case VBI_DEV:
114951694Sroger		return( vbi_close( bktr ) );
115051694Sroger	}
115151694Sroger
115251694Sroger	return( ENXIO );
115351694Sroger}
115451694Sroger
115551694Sroger/*
115651694Sroger *
115751694Sroger */
115851694Srogerint
115951694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag )
116051694Sroger{
116151694Sroger	bktr_ptr_t	bktr;
116251694Sroger	int		unit;
116351694Sroger
116451694Sroger	unit = UNIT(minor(dev));
116551694Sroger	if (unit >= NBKTR)	/* unit out of range */
116651694Sroger		return( ENXIO );
116751694Sroger
116851694Sroger	bktr = &(brooktree[unit]);
116951694Sroger
117051694Sroger	switch ( FUNCTION( minor(dev) ) ) {
117151694Sroger	case VIDEO_DEV:
117251694Sroger		return( video_read( bktr, unit, dev, uio ) );
117351694Sroger	case VBI_DEV:
117451694Sroger		return( vbi_read( bktr, uio, ioflag ) );
117551694Sroger	}
117651694Sroger        return( ENXIO );
117751694Sroger}
117851694Sroger
117951694Sroger
118051694Sroger/*
118151694Sroger *
118251694Sroger */
118351694Srogerint
118451694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag )
118551694Sroger{
118651694Sroger	return( EINVAL ); /* XXX or ENXIO ? */
118751694Sroger}
118851694Sroger
118951694Sroger/*
119051694Sroger *
119151694Sroger */
119251694Srogerint
119383366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td )
119451694Sroger{
119551694Sroger	bktr_ptr_t	bktr;
119651694Sroger	int		unit;
119751694Sroger
119851694Sroger	unit = UNIT(minor(dev));
119951694Sroger	if (unit >= NBKTR)	/* unit out of range */
120051694Sroger		return( ENXIO );
120151694Sroger
120251694Sroger	bktr = &(brooktree[ unit ]);
120351694Sroger
120451694Sroger	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
120551694Sroger		return( ENOMEM );
120651694Sroger
120751694Sroger	switch ( FUNCTION( minor(dev) ) ) {
120851694Sroger	case VIDEO_DEV:
120983366Sjulian		return( video_ioctl( bktr, unit, cmd, arg, td ) );
121051694Sroger	case TUNER_DEV:
121183366Sjulian		return( tuner_ioctl( bktr, unit, cmd, arg, td ) );
121251694Sroger	}
121351694Sroger
121451694Sroger	return( ENXIO );
121551694Sroger}
121651694Sroger
121751694Sroger/*
121851694Sroger * bktr_mmap.
121951694Sroger * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually
122052593Sroger * edit the line below and change  "vm_offset_t" to "int"
122151694Sroger */
122251694Srogerint bktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
122351694Sroger
122451694Sroger{
122551694Sroger	int		unit;
122651694Sroger	bktr_ptr_t	bktr;
122751694Sroger
122851694Sroger	unit = UNIT(minor(dev));
122951694Sroger
123051694Sroger	if (unit >= NBKTR || FUNCTION(minor(dev)) > 0)
123151694Sroger		return( -1 );
123251694Sroger
123351694Sroger	bktr = &(brooktree[ unit ]);
123451694Sroger
123551694Sroger	if (nprot & PROT_EXEC)
123651694Sroger		return( -1 );
123751694Sroger
123851694Sroger	if (offset < 0)
123951694Sroger		return( -1 );
124051694Sroger
124151694Sroger	if (offset >= bktr->alloc_pages * PAGE_SIZE)
124251694Sroger		return( -1 );
124351694Sroger
124451694Sroger	return( i386_btop(vtophys(bktr->bigbuf) + offset) );
124551694Sroger}
124651694Sroger
124783366Sjulianint bktr_poll( dev_t dev, int events, struct thread *td)
124851694Sroger{
124951694Sroger	int		unit;
125051694Sroger	bktr_ptr_t	bktr;
125151694Sroger	int revents = 0;
125251694Sroger
125351694Sroger	unit = UNIT(minor(dev));
125451694Sroger
125551694Sroger	if (unit >= NBKTR)
125651694Sroger		return( -1 );
125751694Sroger
125851694Sroger	bktr = &(brooktree[ unit ]);
125951694Sroger
126051694Sroger	disable_intr();
126151694Sroger
126251694Sroger	if (events & (POLLIN | POLLRDNORM)) {
126351694Sroger
126451694Sroger		switch ( FUNCTION( minor(dev) ) ) {
126551694Sroger		case VBI_DEV:
126651694Sroger			if(bktr->vbisize == 0)
126751694Sroger				selrecord(p, &bktr->vbi_select);
126851694Sroger			else
126951694Sroger				revents |= events & (POLLIN | POLLRDNORM);
127051694Sroger			break;
127151694Sroger		}
127251694Sroger	}
127351694Sroger
127451694Sroger	enable_intr();
127551694Sroger
127651694Sroger	return (revents);
127751694Sroger}
127851694Sroger
127951694Sroger
128051694Sroger#endif		/* FreeBSD 2.2.x and 3.x specific kernel interface routines */
128151694Sroger
128251694Sroger
128351694Sroger/*****************/
128451694Sroger/* *** BSDI  *** */
128551694Sroger/*****************/
128651694Sroger
128751694Sroger#if defined(__bsdi__)
128851694Sroger#endif		/* __bsdi__ BSDI specific kernel interface routines */
128951694Sroger
129051694Sroger
129151694Sroger/*****************************/
129251694Sroger/* *** OpenBSD / NetBSD  *** */
129351694Sroger/*****************************/
129451694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__)
129559014Sroger
129659014Sroger#define IPL_VIDEO       IPL_BIO         /* XXX */
129759014Sroger
129859014Srogerstatic	int		bktr_intr(void *arg) { return common_bktr_intr(arg); }
129959014Sroger
130059014Sroger#define bktr_open       bktropen
130159014Sroger#define bktr_close      bktrclose
130259014Sroger#define bktr_read       bktrread
130359014Sroger#define bktr_write      bktrwrite
130459014Sroger#define bktr_ioctl      bktrioctl
130559014Sroger#define bktr_mmap       bktrmmap
130659014Sroger
130759014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
130859014Sroger                                 vm_offset_t, vm_offset_t);
130959014Sroger
131062112Sroger#if defined(__OpenBSD__)
131192739Salfredstatic int      bktr_probe(struct device *, void *, void *);
131259014Sroger#else
131392739Salfredstatic int      bktr_probe(struct device *, struct cfdata *, void *);
131459014Sroger#endif
131592739Salfredstatic void     bktr_attach(struct device *, struct device *, void *);
131659014Sroger
131759014Srogerstruct cfattach bktr_ca = {
131859014Sroger        sizeof(struct bktr_softc), bktr_probe, bktr_attach
131959014Sroger};
132059014Sroger
132159014Sroger#if defined(__NetBSD__)
132259014Srogerextern struct cfdriver bktr_cd;
132359014Sroger#else
132459014Srogerstruct cfdriver bktr_cd = {
132559014Sroger        NULL, "bktr", DV_DULL
132659014Sroger};
132759014Sroger#endif
132859014Sroger
132962112Srogerint
133062112Srogerbktr_probe(parent, match, aux)
133162112Sroger	struct device *parent;
133262112Sroger#if defined(__OpenBSD__)
133359014Sroger        void *match;
133459014Sroger#else
133559014Sroger        struct cfdata *match;
133659014Sroger#endif
133759014Sroger        void *aux;
133859014Sroger{
133959014Sroger        struct pci_attach_args *pa = aux;
134059014Sroger
134159014Sroger        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
134259014Sroger            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
134359014Sroger             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
134459014Sroger             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
134559014Sroger             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
134659014Sroger                return 1;
134759014Sroger
134859014Sroger        return 0;
134959014Sroger}
135059014Sroger
135159014Sroger
135259014Sroger/*
135359014Sroger * the attach routine.
135459014Sroger */
135559014Srogerstatic void
135662112Srogerbktr_attach(struct device *parent, struct device *self, void *aux)
135759014Sroger{
135859014Sroger	bktr_ptr_t	bktr;
135959014Sroger	u_long		latency;
136059014Sroger	u_long		fun;
136159014Sroger	unsigned int	rev;
136259014Sroger
136359014Sroger#if defined(__OpenBSD__)
136459014Sroger	struct pci_attach_args *pa = aux;
136559014Sroger	pci_chipset_tag_t pc = pa->pa_pc;
136659014Sroger
136759014Sroger	pci_intr_handle_t ih;
136859014Sroger	const char *intrstr;
136959014Sroger	int retval;
137059014Sroger	int unit;
137159014Sroger
137259014Sroger	bktr = (bktr_ptr_t)self;
137359014Sroger	unit = bktr->bktr_dev.dv_unit;
137459014Sroger
137559014Sroger	bktr->pc = pa->pa_pc;
137659014Sroger	bktr->tag = pa->pa_tag;
137759014Sroger        bktr->dmat = pa->pa_dmat;
137859014Sroger
137959014Sroger	/*
138059014Sroger	 * map memory
138159014Sroger	 */
138259014Sroger	bktr->memt = pa->pa_memt;
138359014Sroger	retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START,
138459014Sroger			      &bktr->phys_base, &bktr->obmemsz, NULL);
138559014Sroger	if (!retval)
138659014Sroger		retval = bus_space_map(pa->pa_memt, bktr->phys_base,
138759014Sroger				       bktr->obmemsz, 0, &bktr->memh);
138859014Sroger	if (retval) {
138959014Sroger		printf(": couldn't map memory\n");
139059014Sroger		return;
139159014Sroger	}
139259014Sroger
139359014Sroger
139459014Sroger	/*
139559014Sroger	 * map interrupt
139659014Sroger	 */
139759014Sroger	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
139859014Sroger			 pa->pa_intrline, &ih)) {
139959014Sroger		printf(": couldn't map interrupt\n");
140059014Sroger		return;
140159014Sroger	}
140259014Sroger	intrstr = pci_intr_string(pa->pa_pc, ih);
140359014Sroger
140459014Sroger	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
140559014Sroger				      bktr_intr, bktr, bktr->bktr_dev.dv_xname);
140659014Sroger	if (bktr->ih == NULL) {
140759014Sroger		printf(": couldn't establish interrupt");
140859014Sroger		if (intrstr != NULL)
140959014Sroger			printf(" at %s", intrstr);
141059014Sroger		printf("\n");
141159014Sroger		return;
141259014Sroger	}
141359014Sroger
141459014Sroger	if (intrstr != NULL)
141559014Sroger		printf(": %s\n", intrstr);
141659014Sroger#endif /* __OpenBSD__ */
141759014Sroger
141859014Sroger#if defined(__NetBSD__)
141959014Sroger	struct pci_attach_args *pa = aux;
142059014Sroger	pci_intr_handle_t ih;
142159014Sroger	const char *intrstr;
142259014Sroger	int retval;
142359014Sroger	int unit;
142459014Sroger
142559014Sroger	bktr = (bktr_ptr_t)self;
142659014Sroger	unit = bktr->bktr_dev.dv_unit;
142759014Sroger        bktr->dmat = pa->pa_dmat;
142859014Sroger
142959014Sroger	printf("\n");
143059014Sroger
143159014Sroger	/*
143259014Sroger	 * map memory
143359014Sroger	 */
143459014Sroger	retval = pci_mapreg_map(pa, PCI_MAPREG_START,
143562112Sroger				PCI_MAPREG_TYPE_MEM
143662112Sroger				| PCI_MAPREG_MEM_TYPE_32BIT, 0,
143762112Sroger				&bktr->memt, &bktr->memh, NULL,
143862112Sroger				&bktr->obmemsz);
143962112Sroger	DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n",
144062112Sroger	     bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz));
144159014Sroger	if (retval) {
144262112Sroger		printf("%s: couldn't map memory\n", bktr_name(bktr));
144359014Sroger		return;
144459014Sroger	}
144559014Sroger
144659014Sroger	/*
144759014Sroger	 * Disable the brooktree device
144859014Sroger	 */
144959014Sroger	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
145059014Sroger	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
145159014Sroger
145259014Sroger	/*
145359014Sroger	 * map interrupt
145459014Sroger	 */
145559014Sroger	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
145659014Sroger			 pa->pa_intrline, &ih)) {
145762112Sroger		printf("%s: couldn't map interrupt\n",
145862112Sroger		       bktr_name(bktr));
145959014Sroger		return;
146059014Sroger	}
146159014Sroger	intrstr = pci_intr_string(pa->pa_pc, ih);
146259014Sroger	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
146359014Sroger				      bktr_intr, bktr);
146459014Sroger	if (bktr->ih == NULL) {
146559014Sroger		printf("%s: couldn't establish interrupt",
146662112Sroger		       bktr_name(bktr));
146762112Sroger		if (intrstr != NULL)
146862112Sroger			printf(" at %s", intrstr);
146962112Sroger		printf("\n");
147062112Sroger		return;
147159014Sroger	}
147259014Sroger	if (intrstr != NULL)
147362112Sroger		printf("%s: interrupting at %s\n", bktr_name(bktr),
147459014Sroger		       intrstr);
147559014Sroger#endif /* __NetBSD__ */
147659014Sroger
147759014Sroger/*
147859014Sroger * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
147959014Sroger * you have more than four, then 16 would probably be a better value.
148059014Sroger */
148159014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE
148259014Sroger#define BROOKTREE_DEF_LATENCY_VALUE	10
148359014Sroger#endif
148459014Sroger	latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
148559014Sroger	latency = (latency >> 8) & 0xff;
148659014Sroger
148762112Sroger	if (!latency) {
148862112Sroger		if (bootverbose) {
148959014Sroger			printf("%s: PCI bus latency was 0 changing to %d",
149062112Sroger			       bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
149159014Sroger		}
149259014Sroger		latency = BROOKTREE_DEF_LATENCY_VALUE;
149359014Sroger		pci_conf_write(pa->pa_pc, pa->pa_tag,
149459014Sroger			       PCI_LATENCY_TIMER, latency<<8);
149559014Sroger	}
149659014Sroger
149759014Sroger
149862112Sroger	/* Enabled Bus Master
149962112Sroger	   XXX: check if all old DMA is stopped first (e.g. after warm
150062112Sroger	   boot) */
150159014Sroger	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
150262112Sroger	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
150362112Sroger		       fun | PCI_COMMAND_MASTER_ENABLE);
150459014Sroger
150559014Sroger	/* read the pci id and determine the card type */
150659014Sroger	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
150759014Sroger        rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff;
150859014Sroger
150962112Sroger	common_bktr_attach(bktr, unit, fun, rev);
151059014Sroger}
151159014Sroger
151259014Sroger
151359014Sroger/*
151459014Sroger * Special Memory Allocation
151559014Sroger */
151659014Srogervm_offset_t
151759014Srogerget_bktr_mem(bktr, dmapp, size)
151859014Sroger        bktr_ptr_t bktr;
151959014Sroger        bus_dmamap_t *dmapp;
152059014Sroger        unsigned int size;
152159014Sroger{
152259014Sroger        bus_dma_tag_t dmat = bktr->dmat;
152359014Sroger        bus_dma_segment_t seg;
152459014Sroger        bus_size_t align;
152559014Sroger        int rseg;
152659014Sroger        caddr_t kva;
152759014Sroger
152859014Sroger        /*
152959014Sroger         * Allocate a DMA area
153059014Sroger         */
153159014Sroger        align = 1 << 24;
153259014Sroger        if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
153359014Sroger                             &rseg, BUS_DMA_NOWAIT)) {
153459014Sroger                align = PAGE_SIZE;
153559014Sroger                if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
153659014Sroger                                     &rseg, BUS_DMA_NOWAIT)) {
153762112Sroger                        printf("%s: Unable to dmamem_alloc of %d bytes\n",
153862112Sroger			       bktr_name(bktr), size);
153959014Sroger                        return 0;
154059014Sroger                }
154159014Sroger        }
154259014Sroger        if (bus_dmamem_map(dmat, &seg, rseg, size,
154359014Sroger                           &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
154462112Sroger                printf("%s: Unable to dmamem_map of %d bytes\n",
154562112Sroger                        bktr_name(bktr), size);
154659014Sroger                bus_dmamem_free(dmat, &seg, rseg);
154759014Sroger                return 0;
154859014Sroger        }
154959014Sroger#ifdef __OpenBSD__
155059014Sroger        bktr->dm_mapsize = size;
155159014Sroger#endif
155259014Sroger        /*
155359014Sroger         * Create and locd the DMA map for the DMA area
155459014Sroger         */
155559014Sroger        if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
155662112Sroger                printf("%s: Unable to dmamap_create of %d bytes\n",
155762112Sroger                        bktr_name(bktr), size);
155859014Sroger                bus_dmamem_unmap(dmat, kva, size);
155959014Sroger                bus_dmamem_free(dmat, &seg, rseg);
156059014Sroger                return 0;
156159014Sroger        }
156259014Sroger        if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
156362112Sroger                printf("%s: Unable to dmamap_load of %d bytes\n",
156462112Sroger                        bktr_name(bktr), size);
156559014Sroger                bus_dmamem_unmap(dmat, kva, size);
156659014Sroger                bus_dmamem_free(dmat, &seg, rseg);
156759014Sroger                bus_dmamap_destroy(dmat, *dmapp);
156859014Sroger                return 0;
156959014Sroger        }
157059014Sroger        return (vm_offset_t)kva;
157159014Sroger}
157259014Sroger
157359014Srogervoid
157459014Srogerfree_bktr_mem(bktr, dmap, kva)
157559014Sroger        bktr_ptr_t bktr;
157659014Sroger        bus_dmamap_t dmap;
157759014Sroger        vm_offset_t kva;
157859014Sroger{
157959014Sroger        bus_dma_tag_t dmat = bktr->dmat;
158059014Sroger
158159014Sroger#ifdef __NetBSD__
158259014Sroger        bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
158359014Sroger#else
158459014Sroger        bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize);
158559014Sroger#endif
158659014Sroger        bus_dmamem_free(dmat, dmap->dm_segs, 1);
158759014Sroger        bus_dmamap_destroy(dmat, dmap);
158859014Sroger}
158959014Sroger
159059014Sroger
159159014Sroger/*---------------------------------------------------------
159259014Sroger**
159359014Sroger**	BrookTree 848 character device driver routines
159459014Sroger**
159559014Sroger**---------------------------------------------------------
159659014Sroger*/
159759014Sroger
159859014Sroger
159959014Sroger#define VIDEO_DEV	0x00
160059014Sroger#define TUNER_DEV	0x01
160159014Sroger#define VBI_DEV		0x02
160259014Sroger
160362112Sroger#define UNIT(x)         (minor((x) & 0x0f))
160462112Sroger#define FUNCTION(x)     (minor((x >> 4) & 0x0f))
160559014Sroger
160659014Sroger/*
160759014Sroger *
160859014Sroger */
160959014Srogerint
161083366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td)
161159014Sroger{
161259014Sroger	bktr_ptr_t	bktr;
161359014Sroger	int		unit;
161459014Sroger
161562112Sroger	unit = UNIT(dev);
161659014Sroger
161759014Sroger	/* unit out of range */
161859014Sroger	if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
161962112Sroger		return(ENXIO);
162059014Sroger
162159014Sroger	bktr = bktr_cd.cd_devs[unit];
162259014Sroger
162359014Sroger	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
162462112Sroger		return(ENXIO);
162559014Sroger
162662112Sroger	switch (FUNCTION(dev)) {
162759014Sroger	case VIDEO_DEV:
162862112Sroger		return(video_open(bktr));
162959014Sroger	case TUNER_DEV:
163062112Sroger		return(tuner_open(bktr));
163159014Sroger	case VBI_DEV:
163262112Sroger		return(vbi_open(bktr));
163359014Sroger	}
163459014Sroger
163562112Sroger	return(ENXIO);
163659014Sroger}
163759014Sroger
163859014Sroger
163959014Sroger/*
164059014Sroger *
164159014Sroger */
164259014Srogerint
164383366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td)
164459014Sroger{
164559014Sroger	bktr_ptr_t	bktr;
164659014Sroger	int		unit;
164759014Sroger
164862112Sroger	unit = UNIT(dev);
164959014Sroger
165059014Sroger	bktr = bktr_cd.cd_devs[unit];
165159014Sroger
165262112Sroger	switch (FUNCTION(dev)) {
165359014Sroger	case VIDEO_DEV:
165462112Sroger		return(video_close(bktr));
165559014Sroger	case TUNER_DEV:
165662112Sroger		return(tuner_close(bktr));
165759014Sroger	case VBI_DEV:
165862112Sroger		return(vbi_close(bktr));
165959014Sroger	}
166059014Sroger
166162112Sroger	return(ENXIO);
166259014Sroger}
166359014Sroger
166459014Sroger/*
166559014Sroger *
166659014Sroger */
166759014Srogerint
166862112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag)
166959014Sroger{
167059014Sroger	bktr_ptr_t	bktr;
167159014Sroger	int		unit;
167259014Sroger
167362112Sroger	unit = UNIT(dev);
167459014Sroger
167559014Sroger	bktr = bktr_cd.cd_devs[unit];
167659014Sroger
167762112Sroger	switch (FUNCTION(dev)) {
167859014Sroger	case VIDEO_DEV:
167962112Sroger		return(video_read(bktr, unit, dev, uio));
168059014Sroger	case VBI_DEV:
168162112Sroger		return(vbi_read(bktr, uio, ioflag));
168259014Sroger	}
168359014Sroger
168462112Sroger        return(ENXIO);
168559014Sroger}
168659014Sroger
168759014Sroger
168859014Sroger/*
168959014Sroger *
169059014Sroger */
169159014Srogerint
169262112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag)
169359014Sroger{
169459014Sroger	/* operation not supported */
169562112Sroger	return(EOPNOTSUPP);
169659014Sroger}
169759014Sroger
169859014Sroger/*
169959014Sroger *
170059014Sroger */
170159014Srogerint
170283366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td)
170359014Sroger{
170459014Sroger	bktr_ptr_t	bktr;
170559014Sroger	int		unit;
170659014Sroger
170762112Sroger	unit = UNIT(dev);
170859014Sroger
170959014Sroger	bktr = bktr_cd.cd_devs[unit];
171059014Sroger
171159014Sroger	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
171262112Sroger		return(ENOMEM);
171359014Sroger
171462112Sroger	switch (FUNCTION(dev)) {
171559014Sroger	case VIDEO_DEV:
171662112Sroger		return(video_ioctl(bktr, unit, cmd, arg, pr));
171759014Sroger	case TUNER_DEV:
171862112Sroger		return(tuner_ioctl(bktr, unit, cmd, arg, pr));
171959014Sroger	}
172059014Sroger
172162112Sroger	return(ENXIO);
172259014Sroger}
172359014Sroger
172459014Sroger/*
172559014Sroger *
172659014Sroger */
172762214Srogerpaddr_t
172862214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot)
172959014Sroger{
173059014Sroger	int		unit;
173159014Sroger	bktr_ptr_t	bktr;
173259014Sroger
173362112Sroger	unit = UNIT(dev);
173459014Sroger
173562112Sroger	if (FUNCTION(dev) > 0)	/* only allow mmap on /dev/bktr[n] */
173662112Sroger		return(-1);
173759014Sroger
173859014Sroger	bktr = bktr_cd.cd_devs[unit];
173959014Sroger
174062112Sroger	if ((vaddr_t)offset < 0)
174162112Sroger		return(-1);
174259014Sroger
174362112Sroger	if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
174462112Sroger		return(-1);
174559014Sroger
174659014Sroger#ifdef __NetBSD__
174759014Sroger	return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
174862112Sroger				(vaddr_t)offset, nprot, BUS_DMA_WAITOK));
174959014Sroger#else
175062112Sroger	return(i386_btop(vtophys(bktr->bigbuf) + offset));
175159014Sroger#endif
175259014Sroger}
175359014Sroger
175451694Sroger#endif /* __NetBSD__ || __OpenBSD__ */
1755