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