bktr_os.c revision 331722
1/*-
2 * 1. Redistributions of source code must retain the
3 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by Amancio Hasty and
17 *      Roger Hardiman
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/11/sys/dev/bktr/bktr_os.c 331722 2018-03-29 02:50:57Z eadler $");
36
37/*
38 * This is part of the Driver for Video Capture Cards (Frame grabbers)
39 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
40 * chipset.
41 * Copyright Roger Hardiman and Amancio Hasty.
42 *
43 * bktr_os : This has all the Operating System dependent code,
44 *             probe/attach and open/close/ioctl/read/mmap
45 *             memory allocation
46 *             PCI bus interfacing
47 */
48
49#include "opt_bktr.h"		/* include any kernel config options */
50
51#define FIFO_RISC_DISABLED      0
52#define ALL_INTS_DISABLED       0
53
54
55/*******************/
56/* *** FreeBSD *** */
57/*******************/
58#ifdef __FreeBSD__
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/conf.h>
63#include <sys/uio.h>
64#include <sys/kernel.h>
65#include <sys/module.h>
66#include <sys/signalvar.h>
67#include <sys/malloc.h>
68#include <sys/mman.h>
69#include <sys/poll.h>
70#if __FreeBSD_version >= 500014
71#include <sys/selinfo.h>
72#else
73#include <sys/select.h>
74#endif
75
76#include <vm/vm.h>
77#include <vm/vm_kern.h>
78#include <vm/pmap.h>
79#include <vm/vm_extern.h>
80
81#include <sys/bus.h>		/* used by smbus and newbus */
82
83#include <machine/bus.h>	/* used by bus space and newbus */
84#include <sys/bus.h>
85
86#include <sys/rman.h>		/* used by newbus */
87#include <machine/resource.h>	/* used by newbus */
88
89#if (__FreeBSD_version < 500000)
90#include <machine/clock.h>              /* for DELAY */
91#include <pci/pcivar.h>
92#include <pci/pcireg.h>
93#else
94#include <dev/pci/pcivar.h>
95#include <dev/pci/pcireg.h>
96#endif
97
98#include <sys/sysctl.h>
99int bt848_card = -1;
100int bt848_tuner = -1;
101int bt848_reverse_mute = -1;
102int bt848_format = -1;
103int bt848_slow_msp_audio = -1;
104#ifdef BKTR_NEW_MSP34XX_DRIVER
105int bt848_stereo_once = 0;	/* no continuous stereo monitoring */
106int bt848_amsound = 0;		/* hard-wire AM sound at 6.5 Hz (france),
107				   the autoscan seems work well only with FM... */
108int bt848_dolby = 0;
109#endif
110
111static SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
112SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
113SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
114SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
115SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
116SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
117#ifdef BKTR_NEW_MSP34XX_DRIVER
118SYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, "");
119SYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, "");
120SYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, "");
121#endif
122
123#endif /* end freebsd section */
124
125
126
127/****************/
128/* *** BSDI *** */
129/****************/
130#ifdef __bsdi__
131#endif /* __bsdi__ */
132
133
134/**************************/
135/* *** OpenBSD/NetBSD *** */
136/**************************/
137#if defined(__NetBSD__) || defined(__OpenBSD__)
138
139#include <sys/param.h>
140#include <sys/systm.h>
141#include <sys/conf.h>
142#include <sys/uio.h>
143#include <sys/kernel.h>
144#include <sys/signalvar.h>
145#include <sys/mman.h>
146#include <sys/poll.h>
147#include <sys/select.h>
148#include <sys/vnode.h>
149
150#include <vm/vm.h>
151
152#include <dev/bktr/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
153
154#ifndef __NetBSD__
155#include <vm/vm_kern.h>
156#include <vm/pmap.h>
157#include <vm/vm_extern.h>
158#endif
159
160#include <sys/device.h>
161#include <dev/pci/pcivar.h>
162#include <dev/pci/pcireg.h>
163#include <dev/pci/pcidevs.h>
164
165#define BKTR_DEBUG
166#ifdef BKTR_DEBUG
167int bktr_debug = 0;
168#define DPR(x)	(bktr_debug ? printf x : 0)
169#else
170#define DPR(x)
171#endif
172#endif /* __NetBSD__ || __OpenBSD__ */
173
174
175#ifdef __NetBSD__
176#include <dev/ic/bt8xx.h>	/* NetBSD location for .h files */
177#include <dev/pci/bktr/bktr_reg.h>
178#include <dev/pci/bktr/bktr_tuner.h>
179#include <dev/pci/bktr/bktr_card.h>
180#include <dev/pci/bktr/bktr_audio.h>
181#include <dev/pci/bktr/bktr_core.h>
182#include <dev/pci/bktr/bktr_os.h>
183#else					/* Traditional location for .h files */
184#include <dev/bktr/ioctl_meteor.h>
185#include <dev/bktr/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
186#include <dev/bktr/bktr_reg.h>
187#include <dev/bktr/bktr_tuner.h>
188#include <dev/bktr/bktr_card.h>
189#include <dev/bktr/bktr_audio.h>
190#include <dev/bktr/bktr_core.h>
191#include <dev/bktr/bktr_os.h>
192
193#if defined(BKTR_USE_FREEBSD_SMBUS)
194#include <dev/bktr/bktr_i2c.h>
195
196#include "iicbb_if.h"
197#include "smbus_if.h"
198#endif
199#endif
200
201
202/****************************/
203/* *** FreeBSD 4.x code *** */
204/****************************/
205
206static int	bktr_probe( device_t dev );
207static int	bktr_attach( device_t dev );
208static int	bktr_detach( device_t dev );
209static int	bktr_shutdown( device_t dev );
210static void	bktr_intr(void *arg) { common_bktr_intr(arg); }
211
212static device_method_t bktr_methods[] = {
213	/* Device interface */
214	DEVMETHOD(device_probe,         bktr_probe),
215	DEVMETHOD(device_attach,        bktr_attach),
216	DEVMETHOD(device_detach,        bktr_detach),
217	DEVMETHOD(device_shutdown,      bktr_shutdown),
218
219#if defined(BKTR_USE_FREEBSD_SMBUS)
220	/* iicbb interface */
221	DEVMETHOD(iicbb_callback,	bti2c_iic_callback),
222	DEVMETHOD(iicbb_setsda,		bti2c_iic_setsda),
223	DEVMETHOD(iicbb_setscl,		bti2c_iic_setscl),
224	DEVMETHOD(iicbb_getsda,		bti2c_iic_getsda),
225	DEVMETHOD(iicbb_getscl,		bti2c_iic_getscl),
226	DEVMETHOD(iicbb_reset,		bti2c_iic_reset),
227
228	/* smbus interface */
229	DEVMETHOD(smbus_callback,	bti2c_smb_callback),
230	DEVMETHOD(smbus_writeb,		bti2c_smb_writeb),
231	DEVMETHOD(smbus_writew,		bti2c_smb_writew),
232	DEVMETHOD(smbus_readb,		bti2c_smb_readb),
233#endif
234
235	{ 0, 0 }
236};
237
238static driver_t bktr_driver = {
239	"bktr",
240	bktr_methods,
241	sizeof(struct bktr_softc),
242};
243
244static devclass_t bktr_devclass;
245
246static	d_open_t	bktr_open;
247static	d_close_t	bktr_close;
248static	d_read_t	bktr_read;
249static	d_write_t	bktr_write;
250static	d_ioctl_t	bktr_ioctl;
251static	d_mmap_t	bktr_mmap;
252static	d_poll_t	bktr_poll;
253
254static struct cdevsw bktr_cdevsw = {
255	.d_version =	D_VERSION,
256	.d_flags =	D_NEEDGIANT,
257	.d_open =	bktr_open,
258	.d_close =	bktr_close,
259	.d_read =	bktr_read,
260	.d_write =	bktr_write,
261	.d_ioctl =	bktr_ioctl,
262	.d_poll =	bktr_poll,
263	.d_mmap =	bktr_mmap,
264	.d_name =	"bktr",
265};
266
267#ifdef BKTR_USE_FREEBSD_SMBUS
268#include <dev/iicbus/iiconf.h>
269#include <dev/smbus/smbconf.h>
270MODULE_DEPEND(bktr, iicbb, IICBB_MINVER, IICBB_MODVER, IICBB_MAXVER);
271MODULE_DEPEND(bktr, iicbus, IICBUS_MINVER, IICBUS_MODVER, IICBUS_MAXVER);
272MODULE_DEPEND(bktr, smbus, SMBUS_MINVER, SMBUS_MODVER, SMBUS_MAXVER);
273#endif
274DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0);
275MODULE_DEPEND(bktr, bktr_mem, 1,1,1);
276MODULE_VERSION(bktr, 1);
277
278
279/*
280 * the boot time probe routine.
281 */
282static int
283bktr_probe( device_t dev )
284{
285	unsigned int type = pci_get_devid(dev);
286        unsigned int rev  = pci_get_revid(dev);
287
288	if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
289	{
290		switch (PCI_PRODUCT(type)) {
291		case PCI_PRODUCT_BROOKTREE_BT848:
292			if (rev == 0x12)
293				device_set_desc(dev, "BrookTree 848A");
294			else
295				device_set_desc(dev, "BrookTree 848");
296			return BUS_PROBE_DEFAULT;
297		case PCI_PRODUCT_BROOKTREE_BT849:
298			device_set_desc(dev, "BrookTree 849A");
299			return BUS_PROBE_DEFAULT;
300		case PCI_PRODUCT_BROOKTREE_BT878:
301			device_set_desc(dev, "BrookTree 878");
302			return BUS_PROBE_DEFAULT;
303		case PCI_PRODUCT_BROOKTREE_BT879:
304			device_set_desc(dev, "BrookTree 879");
305			return BUS_PROBE_DEFAULT;
306		}
307	}
308
309        return ENXIO;
310}
311
312
313/*
314 * the attach routine.
315 */
316static int
317bktr_attach( device_t dev )
318{
319	u_long		latency;
320	u_long		fun;
321	unsigned int	rev;
322	unsigned int	unit;
323	int		error = 0;
324#ifdef BROOKTREE_IRQ
325	u_long		old_irq, new_irq;
326#endif
327
328        struct bktr_softc *bktr = device_get_softc(dev);
329
330	unit = device_get_unit(dev);
331
332	/* build the device name for bktr_name() */
333	snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
334
335	/*
336	 * Enable bus mastering and Memory Mapped device
337	 */
338	pci_enable_busmaster(dev);
339
340	/*
341	 * Map control/status registers.
342	 */
343	bktr->mem_rid = PCIR_BAR(0);
344	bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
345					&bktr->mem_rid, RF_ACTIVE);
346
347	if (!bktr->res_mem) {
348		device_printf(dev, "could not map memory\n");
349		error = ENXIO;
350		goto fail;
351	}
352	bktr->memt = rman_get_bustag(bktr->res_mem);
353	bktr->memh = rman_get_bushandle(bktr->res_mem);
354
355
356	/*
357	 * Disable the brooktree device
358	 */
359	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
360	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
361
362
363#ifdef BROOKTREE_IRQ		/* from the configuration file */
364	old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
365	pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
366	new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
367	printf("bktr%d: attach: irq changed from %d to %d\n",
368		unit, (old_irq & 0xff), (new_irq & 0xff));
369#endif
370
371	/*
372	 * Allocate our interrupt.
373	 */
374	bktr->irq_rid = 0;
375	bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
376				&bktr->irq_rid, RF_SHAREABLE | RF_ACTIVE);
377	if (bktr->res_irq == NULL) {
378		device_printf(dev, "could not map interrupt\n");
379		error = ENXIO;
380		goto fail;
381	}
382
383	error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY,
384                               NULL, bktr_intr, bktr, &bktr->res_ih);
385	if (error) {
386		device_printf(dev, "could not setup irq\n");
387		goto fail;
388
389	}
390
391
392	/* Update the Device Control Register */
393	/* on Bt878 and Bt879 cards           */
394	fun = pci_read_config( dev, 0x40, 2);
395        fun = fun | 1;	/* Enable writes to the sub-system vendor ID */
396
397#if defined( BKTR_430_FX_MODE )
398	if (bootverbose) printf("Using 430 FX chipset compatibility mode\n");
399        fun = fun | 2;	/* Enable Intel 430 FX compatibility mode */
400#endif
401
402#if defined( BKTR_SIS_VIA_MODE )
403	if (bootverbose) printf("Using SiS/VIA chipset compatibility mode\n");
404        fun = fun | 4;	/* Enable SiS/VIA compatibility mode (useful for
405                           OPTi chipset motherboards too */
406#endif
407	pci_write_config(dev, 0x40, fun, 2);
408
409#if defined(BKTR_USE_FREEBSD_SMBUS)
410	if (bt848_i2c_attach(dev))
411		printf("bktr%d: i2c_attach: can't attach\n", unit);
412#endif
413
414/*
415 * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
416 * you have more than four, then 16 would probably be a better value.
417 */
418#ifndef BROOKTREE_DEF_LATENCY_VALUE
419#define BROOKTREE_DEF_LATENCY_VALUE	10
420#endif
421	latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4);
422	latency = (latency >> 8) & 0xff;
423	if ( bootverbose ) {
424		if (latency)
425			printf("brooktree%d: PCI bus latency is", unit);
426		else
427			printf("brooktree%d: PCI bus latency was 0 changing to",
428				unit);
429	}
430	if ( !latency ) {
431		latency = BROOKTREE_DEF_LATENCY_VALUE;
432		pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4);
433	}
434	if ( bootverbose ) {
435		printf(" %d.\n", (int) latency);
436	}
437
438	/* read the pci device id and revision id */
439	fun = pci_get_devid(dev);
440        rev = pci_get_revid(dev);
441
442	/* call the common attach code */
443	common_bktr_attach( bktr, unit, fun, rev );
444
445	/* make the device entries */
446	bktr->bktrdev = make_dev(&bktr_cdevsw, unit,
447				0, 0, 0444, "bktr%d",  unit);
448	bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16,
449				0, 0, 0444, "tuner%d", unit);
450	bktr->vbidev  = make_dev(&bktr_cdevsw, unit+32,
451				0, 0, 0444, "vbi%d"  , unit);
452
453
454	/* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */
455	/* alias entries to /dev/bktr /dev/tuner and /dev/vbi */
456#if (__FreeBSD_version >=500000)
457	if (unit == 0) {
458		bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev,  "bktr");
459		bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner");
460		bktr->vbidev_alias  = make_dev_alias(bktr->vbidev,   "vbi");
461	}
462#endif
463
464	return 0;
465
466fail:
467	if (bktr->res_irq)
468		bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
469	if (bktr->res_mem)
470		bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
471	return error;
472
473}
474
475/*
476 * the detach routine.
477 */
478static int
479bktr_detach( device_t dev )
480{
481	struct bktr_softc *bktr = device_get_softc(dev);
482
483#ifdef BKTR_NEW_MSP34XX_DRIVER
484	/* Disable the soundchip and kernel thread */
485	if (bktr->msp3400c_info != NULL)
486		msp_detach(bktr);
487#endif
488
489	/* Disable the brooktree device */
490	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
491	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
492
493#if defined(BKTR_USE_FREEBSD_SMBUS)
494	if (bt848_i2c_detach(dev))
495		printf("bktr%d: i2c_attach: can't attach\n",
496		     device_get_unit(dev));
497#endif
498#ifdef USE_VBIMUTEX
499        mtx_destroy(&bktr->vbimutex);
500#endif
501
502	/* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */
503	/* The memory is retained by the bktr_mem module so we can unload and */
504	/* then reload the main bktr driver module */
505
506	/* Unregister the /dev/bktrN, tunerN and vbiN devices,
507	 * the aliases for unit 0 are automatically destroyed */
508	destroy_dev(bktr->vbidev);
509	destroy_dev(bktr->tunerdev);
510	destroy_dev(bktr->bktrdev);
511
512	/*
513	 * Deallocate resources.
514	 */
515	bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
516	bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
517	bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
518
519	return 0;
520}
521
522/*
523 * the shutdown routine.
524 */
525static int
526bktr_shutdown( device_t dev )
527{
528	struct bktr_softc *bktr = device_get_softc(dev);
529
530	/* Disable the brooktree device */
531	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
532	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
533
534	return 0;
535}
536
537
538/*
539 * Special Memory Allocation
540 */
541vm_offset_t
542get_bktr_mem( int unit, unsigned size )
543{
544	vm_offset_t	addr = 0;
545
546	addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0,
547	    0xffffffff, 1<<24, 0);
548	if (addr == 0)
549		addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0,
550		    0xffffffff, PAGE_SIZE, 0);
551	if (addr == 0) {
552		printf("bktr%d: Unable to allocate %d bytes of memory.\n",
553			unit, size);
554	}
555
556	return( addr );
557}
558
559
560/*---------------------------------------------------------
561**
562**	BrookTree 848 character device driver routines
563**
564**---------------------------------------------------------
565*/
566
567#define VIDEO_DEV	0x00
568#define TUNER_DEV	0x01
569#define VBI_DEV		0x02
570
571#define UNIT(x)		((x) & 0x0f)
572#define FUNCTION(x)	(x >> 4)
573
574/*
575 *
576 */
577static int
578bktr_open( struct cdev *dev, int flags, int fmt, struct thread *td )
579{
580	bktr_ptr_t	bktr;
581	int		unit;
582	int		result;
583
584	unit = UNIT( dev2unit(dev) );
585
586	/* Get the device data */
587	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
588	if (bktr == NULL) {
589		/* the device is no longer valid/functioning */
590		return (ENXIO);
591	}
592
593	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
594		return( ENXIO );
595
596	/* Record that the device is now busy */
597	device_busy(devclass_get_device(bktr_devclass, unit));
598
599
600	if (bt848_card != -1) {
601	  if ((bt848_card >> 8   == unit ) &&
602	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
603	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
604	      bktr->bt848_card = (bt848_card & 0xff);
605	      probeCard(bktr, FALSE, unit);
606	    }
607	  }
608	}
609
610	if (bt848_tuner != -1) {
611	  if ((bt848_tuner >> 8   == unit ) &&
612	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
613	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
614	      bktr->bt848_tuner = (bt848_tuner & 0xff);
615	      probeCard(bktr, FALSE, unit);
616	    }
617	  }
618	}
619
620	if (bt848_reverse_mute != -1) {
621	  if ((bt848_reverse_mute >> 8)   == unit ) {
622	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
623	  }
624	}
625
626	if (bt848_slow_msp_audio != -1) {
627	  if ((bt848_slow_msp_audio >> 8) == unit ) {
628	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
629	  }
630	}
631
632#ifdef BKTR_NEW_MSP34XX_DRIVER
633	if (bt848_stereo_once != 0) {
634	  if ((bt848_stereo_once >> 8) == unit ) {
635	      bktr->stereo_once = (bt848_stereo_once & 0xff);
636	  }
637	}
638
639	if (bt848_amsound != -1) {
640	  if ((bt848_amsound >> 8) == unit ) {
641	      bktr->amsound = (bt848_amsound & 0xff);
642	  }
643	}
644
645	if (bt848_dolby != -1) {
646	  if ((bt848_dolby >> 8) == unit ) {
647	      bktr->dolby = (bt848_dolby & 0xff);
648	  }
649	}
650#endif
651
652	switch ( FUNCTION( dev2unit(dev) ) ) {
653	case VIDEO_DEV:
654		result = video_open( bktr );
655		break;
656	case TUNER_DEV:
657		result = tuner_open( bktr );
658		break;
659	case VBI_DEV:
660		result = vbi_open( bktr );
661		break;
662	default:
663		result = ENXIO;
664		break;
665	}
666
667	/* If there was an error opening the device, undo the busy status */
668	if (result != 0)
669		device_unbusy(devclass_get_device(bktr_devclass, unit));
670	return( result );
671}
672
673
674/*
675 *
676 */
677static int
678bktr_close( struct cdev *dev, int flags, int fmt, struct thread *td )
679{
680	bktr_ptr_t	bktr;
681	int		unit;
682	int		result;
683
684	unit = UNIT( dev2unit(dev) );
685
686	/* Get the device data */
687	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
688	if (bktr == NULL) {
689		/* the device is no longer valid/functioning */
690		return (ENXIO);
691	}
692
693	switch ( FUNCTION( dev2unit(dev) ) ) {
694	case VIDEO_DEV:
695		result = video_close( bktr );
696		break;
697	case TUNER_DEV:
698		result = tuner_close( bktr );
699		break;
700	case VBI_DEV:
701		result = vbi_close( bktr );
702		break;
703	default:
704		return (ENXIO);
705		break;
706	}
707
708	device_unbusy(devclass_get_device(bktr_devclass, unit));
709	return( result );
710}
711
712
713/*
714 *
715 */
716static int
717bktr_read( struct cdev *dev, struct uio *uio, int ioflag )
718{
719	bktr_ptr_t	bktr;
720	int		unit;
721
722	unit = UNIT(dev2unit(dev));
723
724	/* Get the device data */
725	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
726	if (bktr == NULL) {
727		/* the device is no longer valid/functioning */
728		return (ENXIO);
729	}
730
731	switch ( FUNCTION( dev2unit(dev) ) ) {
732	case VIDEO_DEV:
733		return( video_read( bktr, unit, dev, uio ) );
734	case VBI_DEV:
735		return( vbi_read( bktr, uio, ioflag ) );
736	}
737        return( ENXIO );
738}
739
740
741/*
742 *
743 */
744static int
745bktr_write( struct cdev *dev, struct uio *uio, int ioflag )
746{
747	return( EINVAL ); /* XXX or ENXIO ? */
748}
749
750
751/*
752 *
753 */
754static int
755bktr_ioctl( struct cdev *dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td )
756{
757	bktr_ptr_t	bktr;
758	int		unit;
759
760	unit = UNIT(dev2unit(dev));
761
762	/* Get the device data */
763	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
764	if (bktr == NULL) {
765		/* the device is no longer valid/functioning */
766		return (ENXIO);
767	}
768
769#ifdef BKTR_GPIO_ACCESS
770	if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN &&
771	    cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA &&
772	    cmd != BT848_GPIO_SET_DATA)	/* no frame buffer allocated (ioctl failed) */
773		return( ENOMEM );
774#else
775	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
776		return( ENOMEM );
777#endif
778
779	switch ( FUNCTION( dev2unit(dev) ) ) {
780	case VIDEO_DEV:
781		return( video_ioctl( bktr, unit, cmd, arg, td ) );
782	case TUNER_DEV:
783		return( tuner_ioctl( bktr, unit, cmd, arg, td ) );
784	}
785
786	return( ENXIO );
787}
788
789
790/*
791 *
792 */
793static int
794bktr_mmap( struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
795    int nprot, vm_memattr_t *memattr )
796{
797	int		unit;
798	bktr_ptr_t	bktr;
799
800	unit = UNIT(dev2unit(dev));
801
802	if (FUNCTION(dev2unit(dev)) > 0)	/* only allow mmap on /dev/bktr[n] */
803		return( -1 );
804
805	/* Get the device data */
806	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
807	if (bktr == NULL) {
808		/* the device is no longer valid/functioning */
809		return (ENXIO);
810	}
811
812	if (nprot & PROT_EXEC)
813		return( -1 );
814
815	if (offset < 0)
816		return( -1 );
817
818	if (offset >= bktr->alloc_pages * PAGE_SIZE)
819		return( -1 );
820
821	*paddr = vtophys(bktr->bigbuf) + offset;
822	return( 0 );
823}
824
825static int
826bktr_poll( struct cdev *dev, int events, struct thread *td)
827{
828	int		unit;
829	bktr_ptr_t	bktr;
830	int revents = 0;
831	DECLARE_INTR_MASK(s);
832
833	unit = UNIT(dev2unit(dev));
834
835	/* Get the device data */
836	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
837	if (bktr == NULL) {
838		/* the device is no longer valid/functioning */
839		return (ENXIO);
840	}
841
842	LOCK_VBI(bktr);
843	DISABLE_INTR(s);
844
845	if (events & (POLLIN | POLLRDNORM)) {
846
847		switch ( FUNCTION( dev2unit(dev) ) ) {
848		case VBI_DEV:
849			if(bktr->vbisize == 0)
850				selrecord(td, &bktr->vbi_select);
851			else
852				revents |= events & (POLLIN | POLLRDNORM);
853			break;
854		}
855	}
856
857	ENABLE_INTR(s);
858	UNLOCK_VBI(bktr);
859
860	return (revents);
861}
862
863/*****************/
864/* *** BSDI  *** */
865/*****************/
866
867#if defined(__bsdi__)
868#endif		/* __bsdi__ BSDI specific kernel interface routines */
869
870
871/*****************************/
872/* *** OpenBSD / NetBSD  *** */
873/*****************************/
874#if defined(__NetBSD__) || defined(__OpenBSD__)
875
876#define IPL_VIDEO       IPL_BIO         /* XXX */
877
878static	int		bktr_intr(void *arg) { return common_bktr_intr(arg); }
879
880#define bktr_open       bktropen
881#define bktr_close      bktrclose
882#define bktr_read       bktrread
883#define bktr_write      bktrwrite
884#define bktr_ioctl      bktrioctl
885#define bktr_mmap       bktrmmap
886
887vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
888                                 vm_offset_t, vm_offset_t);
889
890#if defined(__OpenBSD__)
891static int      bktr_probe(struct device *, void *, void *);
892#else
893static int      bktr_probe(struct device *, struct cfdata *, void *);
894#endif
895static void     bktr_attach(struct device *, struct device *, void *);
896
897struct cfattach bktr_ca = {
898        sizeof(struct bktr_softc), bktr_probe, bktr_attach
899};
900
901#if defined(__NetBSD__)
902extern struct cfdriver bktr_cd;
903#else
904struct cfdriver bktr_cd = {
905        NULL, "bktr", DV_DULL
906};
907#endif
908
909int
910bktr_probe(parent, match, aux)
911	struct device *parent;
912#if defined(__OpenBSD__)
913        void *match;
914#else
915        struct cfdata *match;
916#endif
917        void *aux;
918{
919        struct pci_attach_args *pa = aux;
920
921        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
922            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
923             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
924             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
925             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
926                return 1;
927
928        return 0;
929}
930
931
932/*
933 * the attach routine.
934 */
935static void
936bktr_attach(struct device *parent, struct device *self, void *aux)
937{
938	bktr_ptr_t	bktr;
939	u_long		latency;
940	u_long		fun;
941	unsigned int	rev;
942
943#if defined(__OpenBSD__)
944	struct pci_attach_args *pa = aux;
945	pci_chipset_tag_t pc = pa->pa_pc;
946
947	pci_intr_handle_t ih;
948	const char *intrstr;
949	int retval;
950	int unit;
951
952	bktr = (bktr_ptr_t)self;
953	unit = bktr->bktr_dev.dv_unit;
954
955	bktr->pc = pa->pa_pc;
956	bktr->tag = pa->pa_tag;
957        bktr->dmat = pa->pa_dmat;
958
959	/*
960	 * map memory
961	 */
962	bktr->memt = pa->pa_memt;
963	retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START,
964			      &bktr->phys_base, &bktr->obmemsz, NULL);
965	if (!retval)
966		retval = bus_space_map(pa->pa_memt, bktr->phys_base,
967				       bktr->obmemsz, 0, &bktr->memh);
968	if (retval) {
969		printf(": couldn't map memory\n");
970		return;
971	}
972
973
974	/*
975	 * map interrupt
976	 */
977	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
978			 pa->pa_intrline, &ih)) {
979		printf(": couldn't map interrupt\n");
980		return;
981	}
982	intrstr = pci_intr_string(pa->pa_pc, ih);
983
984	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
985				      bktr_intr, bktr, bktr->bktr_dev.dv_xname);
986	if (bktr->ih == NULL) {
987		printf(": couldn't establish interrupt");
988		if (intrstr != NULL)
989			printf(" at %s", intrstr);
990		printf("\n");
991		return;
992	}
993
994	if (intrstr != NULL)
995		printf(": %s\n", intrstr);
996#endif /* __OpenBSD__ */
997
998#if defined(__NetBSD__)
999	struct pci_attach_args *pa = aux;
1000	pci_intr_handle_t ih;
1001	const char *intrstr;
1002	int retval;
1003	int unit;
1004
1005	bktr = (bktr_ptr_t)self;
1006	unit = bktr->bktr_dev.dv_unit;
1007        bktr->dmat = pa->pa_dmat;
1008
1009	printf("\n");
1010
1011	/*
1012	 * map memory
1013	 */
1014	retval = pci_mapreg_map(pa, PCI_MAPREG_START,
1015				PCI_MAPREG_TYPE_MEM
1016				| PCI_MAPREG_MEM_TYPE_32BIT, 0,
1017				&bktr->memt, &bktr->memh, NULL,
1018				&bktr->obmemsz);
1019	DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n",
1020	     bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz));
1021	if (retval) {
1022		printf("%s: couldn't map memory\n", bktr_name(bktr));
1023		return;
1024	}
1025
1026	/*
1027	 * Disable the brooktree device
1028	 */
1029	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
1030	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
1031
1032	/*
1033	 * map interrupt
1034	 */
1035	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
1036			 pa->pa_intrline, &ih)) {
1037		printf("%s: couldn't map interrupt\n",
1038		       bktr_name(bktr));
1039		return;
1040	}
1041	intrstr = pci_intr_string(pa->pa_pc, ih);
1042	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
1043				      bktr_intr, bktr);
1044	if (bktr->ih == NULL) {
1045		printf("%s: couldn't establish interrupt",
1046		       bktr_name(bktr));
1047		if (intrstr != NULL)
1048			printf(" at %s", intrstr);
1049		printf("\n");
1050		return;
1051	}
1052	if (intrstr != NULL)
1053		printf("%s: interrupting at %s\n", bktr_name(bktr),
1054		       intrstr);
1055#endif /* __NetBSD__ */
1056
1057/*
1058 * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
1059 * you have more than four, then 16 would probably be a better value.
1060 */
1061#ifndef BROOKTREE_DEF_LATENCY_VALUE
1062#define BROOKTREE_DEF_LATENCY_VALUE	10
1063#endif
1064	latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
1065	latency = (latency >> 8) & 0xff;
1066
1067	if (!latency) {
1068		if (bootverbose) {
1069			printf("%s: PCI bus latency was 0 changing to %d",
1070			       bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
1071		}
1072		latency = BROOKTREE_DEF_LATENCY_VALUE;
1073		pci_conf_write(pa->pa_pc, pa->pa_tag,
1074			       PCI_LATENCY_TIMER, latency<<8);
1075	}
1076
1077
1078	/* Enabled Bus Master
1079	   XXX: check if all old DMA is stopped first (e.g. after warm
1080	   boot) */
1081	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
1082	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
1083		       fun | PCI_COMMAND_MASTER_ENABLE);
1084
1085	/* read the pci id and determine the card type */
1086	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
1087        rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff;
1088
1089	common_bktr_attach(bktr, unit, fun, rev);
1090}
1091
1092
1093/*
1094 * Special Memory Allocation
1095 */
1096vm_offset_t
1097get_bktr_mem(bktr, dmapp, size)
1098        bktr_ptr_t bktr;
1099        bus_dmamap_t *dmapp;
1100        unsigned int size;
1101{
1102        bus_dma_tag_t dmat = bktr->dmat;
1103        bus_dma_segment_t seg;
1104        bus_size_t align;
1105        int rseg;
1106        caddr_t kva;
1107
1108        /*
1109         * Allocate a DMA area
1110         */
1111        align = 1 << 24;
1112        if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1113                             &rseg, BUS_DMA_NOWAIT)) {
1114                align = PAGE_SIZE;
1115                if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1116                                     &rseg, BUS_DMA_NOWAIT)) {
1117                        printf("%s: Unable to dmamem_alloc of %d bytes\n",
1118			       bktr_name(bktr), size);
1119                        return 0;
1120                }
1121        }
1122        if (bus_dmamem_map(dmat, &seg, rseg, size,
1123                           &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1124                printf("%s: Unable to dmamem_map of %d bytes\n",
1125                        bktr_name(bktr), size);
1126                bus_dmamem_free(dmat, &seg, rseg);
1127                return 0;
1128        }
1129#ifdef __OpenBSD__
1130        bktr->dm_mapsize = size;
1131#endif
1132        /*
1133         * Create and locd the DMA map for the DMA area
1134         */
1135        if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
1136                printf("%s: Unable to dmamap_create of %d bytes\n",
1137                        bktr_name(bktr), size);
1138                bus_dmamem_unmap(dmat, kva, size);
1139                bus_dmamem_free(dmat, &seg, rseg);
1140                return 0;
1141        }
1142        if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
1143                printf("%s: Unable to dmamap_load of %d bytes\n",
1144                        bktr_name(bktr), size);
1145                bus_dmamem_unmap(dmat, kva, size);
1146                bus_dmamem_free(dmat, &seg, rseg);
1147                bus_dmamap_destroy(dmat, *dmapp);
1148                return 0;
1149        }
1150        return (vm_offset_t)kva;
1151}
1152
1153void
1154free_bktr_mem(bktr, dmap, kva)
1155        bktr_ptr_t bktr;
1156        bus_dmamap_t dmap;
1157        vm_offset_t kva;
1158{
1159        bus_dma_tag_t dmat = bktr->dmat;
1160
1161#ifdef __NetBSD__
1162        bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
1163#else
1164        bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize);
1165#endif
1166        bus_dmamem_free(dmat, dmap->dm_segs, 1);
1167        bus_dmamap_destroy(dmat, dmap);
1168}
1169
1170
1171/*---------------------------------------------------------
1172**
1173**	BrookTree 848 character device driver routines
1174**
1175**---------------------------------------------------------
1176*/
1177
1178
1179#define VIDEO_DEV	0x00
1180#define TUNER_DEV	0x01
1181#define VBI_DEV		0x02
1182
1183#define UNIT(x)         (dev2unit((x) & 0x0f))
1184#define FUNCTION(x)     (dev2unit((x >> 4) & 0x0f))
1185
1186/*
1187 *
1188 */
1189int
1190bktr_open(dev_t dev, int flags, int fmt, struct thread *td)
1191{
1192	bktr_ptr_t	bktr;
1193	int		unit;
1194
1195	unit = UNIT(dev);
1196
1197	/* unit out of range */
1198	if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
1199		return(ENXIO);
1200
1201	bktr = bktr_cd.cd_devs[unit];
1202
1203	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1204		return(ENXIO);
1205
1206	switch (FUNCTION(dev)) {
1207	case VIDEO_DEV:
1208		return(video_open(bktr));
1209	case TUNER_DEV:
1210		return(tuner_open(bktr));
1211	case VBI_DEV:
1212		return(vbi_open(bktr));
1213	}
1214
1215	return(ENXIO);
1216}
1217
1218
1219/*
1220 *
1221 */
1222int
1223bktr_close(dev_t dev, int flags, int fmt, struct thread *td)
1224{
1225	bktr_ptr_t	bktr;
1226	int		unit;
1227
1228	unit = UNIT(dev);
1229
1230	bktr = bktr_cd.cd_devs[unit];
1231
1232	switch (FUNCTION(dev)) {
1233	case VIDEO_DEV:
1234		return(video_close(bktr));
1235	case TUNER_DEV:
1236		return(tuner_close(bktr));
1237	case VBI_DEV:
1238		return(vbi_close(bktr));
1239	}
1240
1241	return(ENXIO);
1242}
1243
1244/*
1245 *
1246 */
1247int
1248bktr_read(dev_t dev, struct uio *uio, int ioflag)
1249{
1250	bktr_ptr_t	bktr;
1251	int		unit;
1252
1253	unit = UNIT(dev);
1254
1255	bktr = bktr_cd.cd_devs[unit];
1256
1257	switch (FUNCTION(dev)) {
1258	case VIDEO_DEV:
1259		return(video_read(bktr, unit, dev, uio));
1260	case VBI_DEV:
1261		return(vbi_read(bktr, uio, ioflag));
1262	}
1263
1264        return(ENXIO);
1265}
1266
1267
1268/*
1269 *
1270 */
1271int
1272bktr_write(dev_t dev, struct uio *uio, int ioflag)
1273{
1274	/* operation not supported */
1275	return(EOPNOTSUPP);
1276}
1277
1278/*
1279 *
1280 */
1281int
1282bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td)
1283{
1284	bktr_ptr_t	bktr;
1285	int		unit;
1286
1287	unit = UNIT(dev);
1288
1289	bktr = bktr_cd.cd_devs[unit];
1290
1291	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
1292		return(ENOMEM);
1293
1294	switch (FUNCTION(dev)) {
1295	case VIDEO_DEV:
1296		return(video_ioctl(bktr, unit, cmd, arg, pr));
1297	case TUNER_DEV:
1298		return(tuner_ioctl(bktr, unit, cmd, arg, pr));
1299	}
1300
1301	return(ENXIO);
1302}
1303
1304/*
1305 *
1306 */
1307paddr_t
1308bktr_mmap(dev_t dev, off_t offset, int nprot)
1309{
1310	int		unit;
1311	bktr_ptr_t	bktr;
1312
1313	unit = UNIT(dev);
1314
1315	if (FUNCTION(dev) > 0)	/* only allow mmap on /dev/bktr[n] */
1316		return(-1);
1317
1318	bktr = bktr_cd.cd_devs[unit];
1319
1320	if ((vaddr_t)offset < 0)
1321		return(-1);
1322
1323	if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
1324		return(-1);
1325
1326#ifdef __NetBSD__
1327	return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
1328				(vaddr_t)offset, nprot, BUS_DMA_WAITOK));
1329#else
1330	return(i386_btop(vtophys(bktr->bigbuf) + offset));
1331#endif
1332}
1333
1334#endif /* __NetBSD__ || __OpenBSD__ */
1335