bktr_os.c revision 67164
1/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 67164 2000-10-15 14:19:01Z phk $ */
2
3/*
4 * This is part of the Driver for Video Capture Cards (Frame grabbers)
5 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
6 * chipset.
7 * Copyright Roger Hardiman and Amancio Hasty.
8 *
9 * bktr_os : This has all the Operating System dependant code,
10 *             probe/attach and open/close/ioctl/read/mmap
11 *             memory allocation
12 *             PCI bus interfacing
13 *
14 *
15 */
16
17/*
18 * 1. Redistributions of source code must retain the
19 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the above copyright
26 *    notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 *    notice, this list of conditions and the following disclaimer in the
29 *    documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 *    must display the following acknowledgement:
32 *	This product includes software developed by Amancio Hasty and
33 *      Roger Hardiman
34 * 4. The name of the author may not be used to endorse or promote products
35 *    derived from this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
38 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
41 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
46 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 * POSSIBILITY OF SUCH DAMAGE.
48 */
49
50
51#ifdef __FreeBSD__
52#include "bktr.h"
53#endif /* __FreeBSD__ */
54
55#include "opt_bktr.h"		/* include any kernel config options */
56
57#define FIFO_RISC_DISABLED      0
58#define ALL_INTS_DISABLED       0
59
60
61/*******************/
62/* *** FreeBSD *** */
63/*******************/
64#ifdef __FreeBSD__
65
66#include <sys/param.h>
67#include <sys/systm.h>
68#include <sys/conf.h>
69#include <sys/uio.h>
70#include <sys/kernel.h>
71#include <sys/signalvar.h>
72#include <sys/mman.h>
73#include <sys/poll.h>
74#include <sys/select.h>
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) || (NSMBUS > 0)
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
98#include <pci/pcivar.h>
99#include <pci/pcireg.h>
100
101#include <sys/sysctl.h>
102int bt848_card = -1;
103int bt848_tuner = -1;
104int bt848_reverse_mute = -1;
105int bt848_format = -1;
106int bt848_slow_msp_audio = -1;
107
108SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
109SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
110SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
111SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
112SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
113SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
114
115#if (__FreeBSD__ == 2)
116#define PCIR_REVID     PCI_CLASS_REG
117#endif
118
119#endif /* end freebsd section */
120
121
122
123/****************/
124/* *** BSDI *** */
125/****************/
126#ifdef __bsdi__
127#endif /* __bsdi__ */
128
129
130/**************************/
131/* *** OpenBSD/NetBSD *** */
132/**************************/
133#if defined(__NetBSD__) || defined(__OpenBSD__)
134
135#include <sys/param.h>
136#include <sys/systm.h>
137#include <sys/conf.h>
138#include <sys/uio.h>
139#include <sys/kernel.h>
140#include <sys/signalvar.h>
141#include <sys/mman.h>
142#include <sys/poll.h>
143#include <sys/select.h>
144#include <sys/vnode.h>
145
146#include <vm/vm.h>
147
148#ifndef __NetBSD__
149#include <vm/vm_kern.h>
150#include <vm/pmap.h>
151#include <vm/vm_extern.h>
152#endif
153
154#include <sys/device.h>
155#include <dev/pci/pcivar.h>
156#include <dev/pci/pcireg.h>
157#include <dev/pci/pcidevs.h>
158
159#define BKTR_DEBUG
160#ifdef BKTR_DEBUG
161int bktr_debug = 0;
162#define DPR(x)	(bktr_debug ? printf x : 0)
163#else
164#define DPR(x)
165#endif
166#endif /* __NetBSD__ || __OpenBSD__ */
167
168
169#ifdef __NetBSD__
170#include <dev/ic/bt8xx.h>	/* NetBSD location for .h files */
171#include <dev/pci/bktr/bktr_reg.h>
172#include <dev/pci/bktr/bktr_tuner.h>
173#include <dev/pci/bktr/bktr_card.h>
174#include <dev/pci/bktr/bktr_audio.h>
175#include <dev/pci/bktr/bktr_core.h>
176#include <dev/pci/bktr/bktr_os.h>
177#else					/* Traditional location for .h files */
178#include <machine/ioctl_meteor.h>
179#include <machine/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
180#include <dev/bktr/bktr_reg.h>
181#include <dev/bktr/bktr_tuner.h>
182#include <dev/bktr/bktr_card.h>
183#include <dev/bktr/bktr_audio.h>
184#include <dev/bktr/bktr_core.h>
185#include <dev/bktr/bktr_os.h>
186#if defined(BKTR_USE_FREEBSD_SMBUS)
187#include <dev/bktr/bktr_i2c.h>
188#endif
189#endif
190
191
192
193/****************************/
194/* *** FreeBSD 4.x code *** */
195/****************************/
196#if (__FreeBSD_version >= 400000)
197
198static int	bktr_probe( device_t dev );
199static int	bktr_attach( device_t dev );
200static int	bktr_detach( device_t dev );
201static int	bktr_shutdown( device_t dev );
202static void	bktr_intr(void *arg) { common_bktr_intr(arg); }
203
204static device_method_t bktr_methods[] = {
205	/* Device interface */
206	DEVMETHOD(device_probe,         bktr_probe),
207	DEVMETHOD(device_attach,        bktr_attach),
208	DEVMETHOD(device_detach,        bktr_detach),
209	DEVMETHOD(device_shutdown,      bktr_shutdown),
210
211	{ 0, 0 }
212};
213
214static driver_t bktr_driver = {
215	"bktr",
216	bktr_methods,
217	sizeof(struct bktr_softc),
218};
219
220static devclass_t bktr_devclass;
221
222static	d_open_t	bktr_open;
223static	d_close_t	bktr_close;
224static	d_read_t	bktr_read;
225static	d_write_t	bktr_write;
226static	d_ioctl_t	bktr_ioctl;
227static	d_mmap_t	bktr_mmap;
228static	d_poll_t	bktr_poll;
229
230#define CDEV_MAJOR 92
231static struct cdevsw bktr_cdevsw = {
232	/* open */	bktr_open,
233	/* close */	bktr_close,
234	/* read */	bktr_read,
235	/* write */	bktr_write,
236	/* ioctl */	bktr_ioctl,
237	/* poll */	bktr_poll,
238	/* mmap */	bktr_mmap,
239	/* strategy */	nostrategy,
240	/* name */	"bktr",
241	/* maj */	CDEV_MAJOR,
242	/* dump */	nodump,
243	/* psize */	nopsize,
244	/* flags */	0,
245	/* bmaj */	-1
246};
247
248DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0);
249MODULE_DEPEND(bktr, bktr_mem, 1,1,1);
250MODULE_VERSION(bktr, 1);
251
252
253/*
254 * the boot time probe routine.
255 */
256static int
257bktr_probe( device_t dev )
258{
259	unsigned int type = pci_get_devid(dev);
260        unsigned int rev  = pci_get_revid(dev);
261
262	switch (type) {
263	case BROOKTREE_848_PCI_ID:
264		if (rev == 0x12) device_set_desc(dev, "BrookTree 848A");
265		else             device_set_desc(dev, "BrookTree 848");
266                return 0;
267        case BROOKTREE_849_PCI_ID:
268                device_set_desc(dev, "BrookTree 849A");
269                return 0;
270        case BROOKTREE_878_PCI_ID:
271                device_set_desc(dev, "BrookTree 878");
272                return 0;
273        case BROOKTREE_879_PCI_ID:
274                device_set_desc(dev, "BrookTree 879");
275                return 0;
276	};
277
278        return ENXIO;
279}
280
281
282/*
283 * the attach routine.
284 */
285static int
286bktr_attach( device_t dev )
287{
288	u_long		latency;
289	u_long		fun;
290	u_long		val;
291	unsigned int	rev;
292	unsigned int	unit;
293	int		error = 0;
294#ifdef BROOKTREE_IRQ
295	u_long		old_irq, new_irq;
296#endif
297
298        struct bktr_softc *bktr = device_get_softc(dev);
299
300	unit = device_get_unit(dev);
301
302	/* build the device name for bktr_name() */
303	snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
304
305	/*
306	 * Enable bus mastering and Memory Mapped device
307	 */
308	val = pci_read_config(dev, PCIR_COMMAND, 4);
309	val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
310	pci_write_config(dev, PCIR_COMMAND, val, 4);
311
312	/*
313	 * Map control/status registers.
314	 */
315	bktr->mem_rid = PCIR_MAPS;
316	bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid,
317					0, ~0, 1, RF_ACTIVE);
318
319
320	if (!bktr->res_mem) {
321		device_printf(dev, "could not map memory\n");
322		error = ENXIO;
323		goto fail;
324	}
325	bktr->memt = rman_get_bustag(bktr->res_mem);
326	bktr->memh = rman_get_bushandle(bktr->res_mem);
327
328
329	/*
330	 * Disable the brooktree device
331	 */
332	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
333	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
334
335
336#ifdef BROOKTREE_IRQ		/* from the configuration file */
337	old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
338	pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
339	new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
340	printf("bktr%d: attach: irq changed from %d to %d\n",
341		unit, (old_irq & 0xff), (new_irq & 0xff));
342#endif
343
344	/*
345	 * Allocate our interrupt.
346	 */
347	bktr->irq_rid = 0;
348	bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid,
349				0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
350	if (bktr->res_irq == NULL) {
351		device_printf(dev, "could not map interrupt\n");
352		error = ENXIO;
353		goto fail;
354	}
355
356	error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY,
357                               bktr_intr, bktr, &bktr->res_ih);
358	if (error) {
359		device_printf(dev, "could not setup irq\n");
360		goto fail;
361
362	}
363
364
365	/* Update the Device Control Register */
366	/* on Bt878 and Bt879 cards           */
367	fun = pci_read_config( dev, 0x40, 2);
368        fun = fun | 1;	/* Enable writes to the sub-system vendor ID */
369
370#if defined( BKTR_430_FX_MODE )
371	if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
372        fun = fun | 2;	/* Enable Intel 430 FX compatibility mode */
373#endif
374
375#if defined( BKTR_SIS_VIA_MODE )
376	if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
377        fun = fun | 4;	/* Enable SiS/VIA compatibility mode (usefull for
378                           OPTi chipset motherboards too */
379#endif
380	pci_write_config(dev, 0x40, fun, 2);
381
382
383	/* XXX call bt848_i2c dependent attach() routine */
384#if defined(BKTR_USE_FREEBSD_SMBUS)
385	if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc))
386		printf("bktr%d: i2c_attach: can't attach\n", unit);
387#endif
388
389
390/*
391 * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
392 * you have more than four, then 16 would probably be a better value.
393 */
394#ifndef BROOKTREE_DEF_LATENCY_VALUE
395#define BROOKTREE_DEF_LATENCY_VALUE	10
396#endif
397	latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4);
398	latency = (latency >> 8) & 0xff;
399	if ( bootverbose ) {
400		if (latency)
401			printf("brooktree%d: PCI bus latency is", unit);
402		else
403			printf("brooktree%d: PCI bus latency was 0 changing to",
404				unit);
405	}
406	if ( !latency ) {
407		latency = BROOKTREE_DEF_LATENCY_VALUE;
408		pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4);
409	}
410	if ( bootverbose ) {
411		printf(" %d.\n", (int) latency);
412	}
413
414	/* read the pci device id and revision id */
415	fun = pci_get_devid(dev);
416        rev = pci_get_revid(dev);
417
418	/* call the common attach code */
419	common_bktr_attach( bktr, unit, fun, rev );
420
421	make_dev(&bktr_cdevsw, unit,    0, 0, 0444, "bktr%d",  unit);
422	make_dev(&bktr_cdevsw, unit+16, 0, 0, 0444, "tuner%d", unit);
423	make_dev(&bktr_cdevsw, unit+32, 0, 0, 0444, "vbi%d", unit);
424
425	return 0;
426
427fail:
428	if (bktr->res_irq)
429		bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
430	if (bktr->res_mem)
431		bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem);
432	return error;
433
434}
435
436/*
437 * the detach routine.
438 */
439static int
440bktr_detach( device_t dev )
441{
442	struct bktr_softc *bktr = device_get_softc(dev);
443
444	/* Disable the brooktree device */
445	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
446	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
447
448	/* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */
449
450	/*
451	 * Deallocate resources.
452	 */
453	bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
454	bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
455	bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
456
457	return 0;
458}
459
460/*
461 * the shutdown routine.
462 */
463static int
464bktr_shutdown( device_t dev )
465{
466	struct bktr_softc *bktr = device_get_softc(dev);
467
468	/* Disable the brooktree device */
469	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
470	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
471
472	return 0;
473}
474
475
476/*
477 * Special Memory Allocation
478 */
479vm_offset_t
480get_bktr_mem( int unit, unsigned size )
481{
482	vm_offset_t	addr = 0;
483
484	addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
485	if (addr == 0)
486		addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
487	if (addr == 0) {
488		printf("bktr%d: Unable to allocate %d bytes of memory.\n",
489			unit, size);
490	}
491
492	return( addr );
493}
494
495
496/*---------------------------------------------------------
497**
498**	BrookTree 848 character device driver routines
499**
500**---------------------------------------------------------
501*/
502
503#define VIDEO_DEV	0x00
504#define TUNER_DEV	0x01
505#define VBI_DEV		0x02
506
507#define UNIT(x)		((x) & 0x0f)
508#define FUNCTION(x)	(x >> 4)
509
510/*
511 *
512 */
513int
514bktr_open( dev_t dev, int flags, int fmt, struct proc *p )
515{
516	bktr_ptr_t	bktr;
517	int		unit;
518	int		result;
519
520	unit = UNIT( minor(dev) );
521
522	/* Get the device data */
523	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
524	if (bktr == NULL) {
525		/* the device is no longer valid/functioning */
526		return (ENXIO);
527	}
528
529	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
530		return( ENXIO );
531
532	/* Record that the device is now busy */
533	device_busy(devclass_get_device(bktr_devclass, unit));
534
535
536	if (bt848_card != -1) {
537	  if ((bt848_card >> 8   == unit ) &&
538	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
539	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
540	      bktr->bt848_card = (bt848_card & 0xff);
541	      probeCard(bktr, FALSE, unit);
542	    }
543	  }
544	}
545
546	if (bt848_tuner != -1) {
547	  if ((bt848_tuner >> 8   == unit ) &&
548	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
549	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
550	      bktr->bt848_tuner = (bt848_tuner & 0xff);
551	      probeCard(bktr, FALSE, unit);
552	    }
553	  }
554	}
555
556	if (bt848_reverse_mute != -1) {
557	  if ((bt848_reverse_mute >> 8)   == unit ) {
558	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
559	  }
560	}
561
562	if (bt848_slow_msp_audio != -1) {
563	  if ((bt848_slow_msp_audio >> 8) == unit ) {
564	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
565	  }
566	}
567
568	switch ( FUNCTION( minor(dev) ) ) {
569	case VIDEO_DEV:
570		result = video_open( bktr );
571		break;
572	case TUNER_DEV:
573		result = tuner_open( bktr );
574		break;
575	case VBI_DEV:
576		result = vbi_open( bktr );
577		break;
578	default:
579		result = ENXIO;
580		break;
581	}
582
583	/* If there was an error opening the device, undo the busy status */
584	if (result != 0)
585		device_unbusy(devclass_get_device(bktr_devclass, unit));
586	return( result );
587}
588
589
590/*
591 *
592 */
593int
594bktr_close( dev_t dev, int flags, int fmt, struct proc *p )
595{
596	bktr_ptr_t	bktr;
597	int		unit;
598	int		result;
599
600	unit = UNIT( minor(dev) );
601
602	/* Get the device data */
603	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
604	if (bktr == NULL) {
605		/* the device is no longer valid/functioning */
606		return (ENXIO);
607	}
608
609	switch ( FUNCTION( minor(dev) ) ) {
610	case VIDEO_DEV:
611		result = video_close( bktr );
612		break;
613	case TUNER_DEV:
614		result = tuner_close( bktr );
615		break;
616	case VBI_DEV:
617		result = vbi_close( bktr );
618		break;
619	default:
620		return (ENXIO);
621		break;
622	}
623
624	device_unbusy(devclass_get_device(bktr_devclass, unit));
625	return( result );
626}
627
628
629/*
630 *
631 */
632int
633bktr_read( dev_t dev, struct uio *uio, int ioflag )
634{
635	bktr_ptr_t	bktr;
636	int		unit;
637
638	unit = UNIT(minor(dev));
639
640	/* Get the device data */
641	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
642	if (bktr == NULL) {
643		/* the device is no longer valid/functioning */
644		return (ENXIO);
645	}
646
647	switch ( FUNCTION( minor(dev) ) ) {
648	case VIDEO_DEV:
649		return( video_read( bktr, unit, dev, uio ) );
650	case VBI_DEV:
651		return( vbi_read( bktr, uio, ioflag ) );
652	}
653        return( ENXIO );
654}
655
656
657/*
658 *
659 */
660int
661bktr_write( dev_t dev, struct uio *uio, int ioflag )
662{
663	return( EINVAL ); /* XXX or ENXIO ? */
664}
665
666
667/*
668 *
669 */
670int
671bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr )
672{
673	bktr_ptr_t	bktr;
674	int		unit;
675
676	unit = UNIT(minor(dev));
677
678	/* Get the device data */
679	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
680	if (bktr == NULL) {
681		/* the device is no longer valid/functioning */
682		return (ENXIO);
683	}
684
685	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
686		return( ENOMEM );
687
688	switch ( FUNCTION( minor(dev) ) ) {
689	case VIDEO_DEV:
690		return( video_ioctl( bktr, unit, cmd, arg, pr ) );
691	case TUNER_DEV:
692		return( tuner_ioctl( bktr, unit, cmd, arg, pr ) );
693	}
694
695	return( ENXIO );
696}
697
698
699/*
700 *
701 */
702int
703bktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
704{
705	int		unit;
706	bktr_ptr_t	bktr;
707
708	unit = UNIT(minor(dev));
709
710	if (FUNCTION(minor(dev)) > 0)	/* only allow mmap on /dev/bktr[n] */
711		return( -1 );
712
713	/* Get the device data */
714	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
715	if (bktr == NULL) {
716		/* the device is no longer valid/functioning */
717		return (ENXIO);
718	}
719
720	if (nprot & PROT_EXEC)
721		return( -1 );
722
723	if (offset < 0)
724		return( -1 );
725
726	if (offset >= bktr->alloc_pages * PAGE_SIZE)
727		return( -1 );
728
729	return( atop(vtophys(bktr->bigbuf) + offset) );
730}
731
732int bktr_poll( dev_t dev, int events, struct proc *p)
733{
734	int		unit;
735	bktr_ptr_t	bktr;
736	int revents = 0;
737	DECLARE_INTR_MASK(s);
738
739	unit = UNIT(minor(dev));
740
741	/* Get the device data */
742	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
743	if (bktr == NULL) {
744		/* the device is no longer valid/functioning */
745		return (ENXIO);
746	}
747
748	DISABLE_INTR(s);
749
750	if (events & (POLLIN | POLLRDNORM)) {
751
752		switch ( FUNCTION( minor(dev) ) ) {
753		case VBI_DEV:
754			if(bktr->vbisize == 0)
755				selrecord(p, &bktr->vbi_select);
756			else
757				revents |= events & (POLLIN | POLLRDNORM);
758			break;
759		}
760	}
761
762	ENABLE_INTR(s);
763
764	return (revents);
765}
766
767#endif		/* FreeBSD 4.x specific kernel interface routines */
768
769/**********************************/
770/* *** FreeBSD 2.2.x and 3.x  *** */
771/**********************************/
772
773#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3))
774
775static bktr_reg_t brooktree[ NBKTR ];
776
777static const char*	bktr_probe( pcici_t tag, pcidi_t type );
778static void		bktr_attach( pcici_t tag, int unit );
779static void		bktr_intr(void *arg) { common_bktr_intr(arg); }
780
781static u_long	bktr_count;
782
783static struct	pci_device bktr_device = {
784	"bktr",
785	bktr_probe,
786	bktr_attach,
787	&bktr_count
788};
789
790DATA_SET (pcidevice_set, bktr_device);
791
792static	d_open_t	bktr_open;
793static	d_close_t	bktr_close;
794static	d_read_t	bktr_read;
795static	d_write_t	bktr_write;
796static	d_ioctl_t	bktr_ioctl;
797static	d_mmap_t	bktr_mmap;
798static	d_poll_t	bktr_poll;
799
800#define CDEV_MAJOR 92
801static struct cdevsw bktr_cdevsw =
802{
803	bktr_open,	bktr_close,	bktr_read,	bktr_write,
804	bktr_ioctl,	nostop,		nullreset,	nodevtotty,
805	bktr_poll,	bktr_mmap,	NULL,		"bktr",
806	NULL,		-1
807};
808
809static int bktr_devsw_installed;
810
811static void
812bktr_drvinit( void *unused )
813{
814	dev_t dev;
815
816	if ( ! bktr_devsw_installed ) {
817		dev = makedev(CDEV_MAJOR, 0);
818		cdevsw_add(&dev,&bktr_cdevsw, NULL);
819		bktr_devsw_installed = 1;
820	}
821}
822
823SYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL)
824
825/*
826 * the boot time probe routine.
827 */
828static const char*
829bktr_probe( pcici_t tag, pcidi_t type )
830{
831        unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff;
832
833	switch (type) {
834	case BROOKTREE_848_PCI_ID:
835		if (rev == 0x12) return("BrookTree 848A");
836		else             return("BrookTree 848");
837        case BROOKTREE_849_PCI_ID:
838                return("BrookTree 849A");
839        case BROOKTREE_878_PCI_ID:
840                return("BrookTree 878");
841        case BROOKTREE_879_PCI_ID:
842                return("BrookTree 879");
843	};
844
845	return ((char *)0);
846}
847
848/*
849 * the attach routine.
850 */
851static	void
852bktr_attach( pcici_t tag, int unit )
853{
854	bktr_ptr_t	bktr;
855	u_long		latency;
856	u_long		fun;
857	unsigned int	rev;
858	unsigned long	base;
859#ifdef BROOKTREE_IRQ
860	u_long		old_irq, new_irq;
861#endif
862
863	bktr = &brooktree[unit];
864
865	if (unit >= NBKTR) {
866		printf("brooktree%d: attach: only %d units configured.\n",
867		        unit, NBKTR);
868		printf("brooktree%d: attach: invalid unit number.\n", unit);
869		return;
870	}
871
872	/* build the device name for bktr_name() */
873	snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
874
875	/* Enable Memory Mapping */
876	fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
877	pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2);
878
879	/* Enable Bus Mastering */
880	fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
881	pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4);
882
883	bktr->tag = tag;
884
885
886	/*
887	 * Map control/status registers
888	 */
889	pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base,
890		     &bktr->phys_base );
891#if (__FreeBSD_version >= 300000)
892	bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */
893	bktr->memh = (bus_space_handle_t)base; /* XXX functions here */
894#endif
895
896	/*
897	 * Disable the brooktree device
898	 */
899	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
900	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
901
902#ifdef BROOKTREE_IRQ		/* from the configuration file */
903	old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
904	pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
905	new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
906	printf("bktr%d: attach: irq changed from %d to %d\n",
907		unit, (old_irq & 0xff), (new_irq & 0xff));
908#endif
909
910	/*
911	 * setup the interrupt handling routine
912	 */
913	pci_map_int(tag, bktr_intr, (void*) bktr, &tty_imask);
914
915
916	/* Update the Device Control Register */
917	/* on Bt878 and Bt879 cards */
918	fun = pci_conf_read(tag, 0x40);
919        fun = fun | 1;	/* Enable writes to the sub-system vendor ID */
920
921#if defined( BKTR_430_FX_MODE )
922	if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
923        fun = fun | 2;	/* Enable Intel 430 FX compatibility mode */
924#endif
925
926#if defined( BKTR_SIS_VIA_MODE )
927	if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
928        fun = fun | 4;	/* Enable SiS/VIA compatibility mode (usefull for
929                           OPTi chipset motherboards too */
930#endif
931	pci_conf_write(tag, 0x40, fun);
932
933
934	/* XXX call bt848_i2c dependent attach() routine */
935#if defined(BKTR_USE_FREEBSD_SMBUS)
936	if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc))
937		printf("bktr%d: i2c_attach: can't attach\n", unit);
938#endif
939
940
941/*
942 * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
943 * you have more than four, then 16 would probably be a better value.
944 */
945#ifndef BROOKTREE_DEF_LATENCY_VALUE
946#define BROOKTREE_DEF_LATENCY_VALUE	10
947#endif
948	latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
949	latency = (latency >> 8) & 0xff;
950	if ( bootverbose ) {
951		if (latency)
952			printf("brooktree%d: PCI bus latency is", unit);
953		else
954			printf("brooktree%d: PCI bus latency was 0 changing to",
955				unit);
956	}
957	if ( !latency ) {
958		latency = BROOKTREE_DEF_LATENCY_VALUE;
959		pci_conf_write(tag, PCI_LATENCY_TIMER,	latency<<8);
960	}
961	if ( bootverbose ) {
962		printf(" %d.\n", (int) latency);
963	}
964
965
966	/* read the pci device id and revision id */
967	fun = pci_conf_read(tag, PCI_ID_REG);
968        rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff;
969
970	/* call the common attach code */
971	common_bktr_attach( bktr, unit, fun, rev );
972
973}
974
975
976/*
977 * Special Memory Allocation
978 */
979vm_offset_t
980get_bktr_mem( int unit, unsigned size )
981{
982	vm_offset_t	addr = 0;
983
984	addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24);
985	if (addr == 0)
986		addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff,
987								PAGE_SIZE);
988	if (addr == 0) {
989		printf("bktr%d: Unable to allocate %d bytes of memory.\n",
990			unit, size);
991	}
992
993	return( addr );
994}
995
996/*---------------------------------------------------------
997**
998**	BrookTree 848 character device driver routines
999**
1000**---------------------------------------------------------
1001*/
1002
1003
1004#define VIDEO_DEV	0x00
1005#define TUNER_DEV	0x01
1006#define VBI_DEV		0x02
1007
1008#define UNIT(x)		((x) & 0x0f)
1009#define FUNCTION(x)	((x >> 4) & 0x0f)
1010
1011
1012/*
1013 *
1014 */
1015int
1016bktr_open( dev_t dev, int flags, int fmt, struct proc *p )
1017{
1018	bktr_ptr_t	bktr;
1019	int		unit;
1020
1021	unit = UNIT( minor(dev) );
1022	if (unit >= NBKTR)			/* unit out of range */
1023		return( ENXIO );
1024
1025	bktr = &(brooktree[ unit ]);
1026
1027	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1028		return( ENXIO );
1029
1030
1031	if (bt848_card != -1) {
1032	  if ((bt848_card >> 8   == unit ) &&
1033	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
1034	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
1035	      bktr->bt848_card = (bt848_card & 0xff);
1036	      probeCard(bktr, FALSE, unit);
1037	    }
1038	  }
1039	}
1040
1041	if (bt848_tuner != -1) {
1042	  if ((bt848_tuner >> 8   == unit ) &&
1043	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
1044	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
1045	      bktr->bt848_tuner = (bt848_tuner & 0xff);
1046	      probeCard(bktr, FALSE, unit);
1047	    }
1048	  }
1049	}
1050
1051	if (bt848_reverse_mute != -1) {
1052	  if ((bt848_reverse_mute >> 8)   == unit ) {
1053	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
1054	  }
1055	}
1056
1057	if (bt848_slow_msp_audio != -1) {
1058	  if ((bt848_slow_msp_audio >> 8) == unit ) {
1059	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
1060	  }
1061	}
1062
1063	switch ( FUNCTION( minor(dev) ) ) {
1064	case VIDEO_DEV:
1065		return( video_open( bktr ) );
1066	case TUNER_DEV:
1067		return( tuner_open( bktr ) );
1068	case VBI_DEV:
1069		return( vbi_open( bktr ) );
1070	}
1071	return( ENXIO );
1072}
1073
1074
1075/*
1076 *
1077 */
1078int
1079bktr_close( dev_t dev, int flags, int fmt, struct proc *p )
1080{
1081	bktr_ptr_t	bktr;
1082	int		unit;
1083
1084	unit = UNIT( minor(dev) );
1085	if (unit >= NBKTR)			/* unit out of range */
1086		return( ENXIO );
1087
1088	bktr = &(brooktree[ unit ]);
1089
1090	switch ( FUNCTION( minor(dev) ) ) {
1091	case VIDEO_DEV:
1092		return( video_close( bktr ) );
1093	case TUNER_DEV:
1094		return( tuner_close( bktr ) );
1095	case VBI_DEV:
1096		return( vbi_close( bktr ) );
1097	}
1098
1099	return( ENXIO );
1100}
1101
1102/*
1103 *
1104 */
1105int
1106bktr_read( dev_t dev, struct uio *uio, int ioflag )
1107{
1108	bktr_ptr_t	bktr;
1109	int		unit;
1110
1111	unit = UNIT(minor(dev));
1112	if (unit >= NBKTR)	/* unit out of range */
1113		return( ENXIO );
1114
1115	bktr = &(brooktree[unit]);
1116
1117	switch ( FUNCTION( minor(dev) ) ) {
1118	case VIDEO_DEV:
1119		return( video_read( bktr, unit, dev, uio ) );
1120	case VBI_DEV:
1121		return( vbi_read( bktr, uio, ioflag ) );
1122	}
1123        return( ENXIO );
1124}
1125
1126
1127/*
1128 *
1129 */
1130int
1131bktr_write( dev_t dev, struct uio *uio, int ioflag )
1132{
1133	return( EINVAL ); /* XXX or ENXIO ? */
1134}
1135
1136/*
1137 *
1138 */
1139int
1140bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr )
1141{
1142	bktr_ptr_t	bktr;
1143	int		unit;
1144
1145	unit = UNIT(minor(dev));
1146	if (unit >= NBKTR)	/* unit out of range */
1147		return( ENXIO );
1148
1149	bktr = &(brooktree[ unit ]);
1150
1151	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
1152		return( ENOMEM );
1153
1154	switch ( FUNCTION( minor(dev) ) ) {
1155	case VIDEO_DEV:
1156		return( video_ioctl( bktr, unit, cmd, arg, pr ) );
1157	case TUNER_DEV:
1158		return( tuner_ioctl( bktr, unit, cmd, arg, pr ) );
1159	}
1160
1161	return( ENXIO );
1162}
1163
1164/*
1165 * bktr_mmap.
1166 * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually
1167 * edit the line below and change  "vm_offset_t" to "int"
1168 */
1169int bktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
1170
1171{
1172	int		unit;
1173	bktr_ptr_t	bktr;
1174
1175	unit = UNIT(minor(dev));
1176
1177	if (unit >= NBKTR || FUNCTION(minor(dev)) > 0)
1178		return( -1 );
1179
1180	bktr = &(brooktree[ unit ]);
1181
1182	if (nprot & PROT_EXEC)
1183		return( -1 );
1184
1185	if (offset < 0)
1186		return( -1 );
1187
1188	if (offset >= bktr->alloc_pages * PAGE_SIZE)
1189		return( -1 );
1190
1191	return( i386_btop(vtophys(bktr->bigbuf) + offset) );
1192}
1193
1194int bktr_poll( dev_t dev, int events, struct proc *p)
1195{
1196	int		unit;
1197	bktr_ptr_t	bktr;
1198	int revents = 0;
1199
1200	unit = UNIT(minor(dev));
1201
1202	if (unit >= NBKTR)
1203		return( -1 );
1204
1205	bktr = &(brooktree[ unit ]);
1206
1207	disable_intr();
1208
1209	if (events & (POLLIN | POLLRDNORM)) {
1210
1211		switch ( FUNCTION( minor(dev) ) ) {
1212		case VBI_DEV:
1213			if(bktr->vbisize == 0)
1214				selrecord(p, &bktr->vbi_select);
1215			else
1216				revents |= events & (POLLIN | POLLRDNORM);
1217			break;
1218		}
1219	}
1220
1221	enable_intr();
1222
1223	return (revents);
1224}
1225
1226
1227#endif		/* FreeBSD 2.2.x and 3.x specific kernel interface routines */
1228
1229
1230/*****************/
1231/* *** BSDI  *** */
1232/*****************/
1233
1234#if defined(__bsdi__)
1235#endif		/* __bsdi__ BSDI specific kernel interface routines */
1236
1237
1238/*****************************/
1239/* *** OpenBSD / NetBSD  *** */
1240/*****************************/
1241#if defined(__NetBSD__) || defined(__OpenBSD__)
1242
1243#define IPL_VIDEO       IPL_BIO         /* XXX */
1244
1245static	int		bktr_intr(void *arg) { return common_bktr_intr(arg); }
1246
1247#define bktr_open       bktropen
1248#define bktr_close      bktrclose
1249#define bktr_read       bktrread
1250#define bktr_write      bktrwrite
1251#define bktr_ioctl      bktrioctl
1252#define bktr_mmap       bktrmmap
1253
1254vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
1255                                 vm_offset_t, vm_offset_t);
1256
1257#if defined(__OpenBSD__)
1258static int      bktr_probe __P((struct device *, void *, void *));
1259#else
1260static int      bktr_probe __P((struct device *, struct cfdata *, void *));
1261#endif
1262static void     bktr_attach __P((struct device *, struct device *, void *));
1263
1264struct cfattach bktr_ca = {
1265        sizeof(struct bktr_softc), bktr_probe, bktr_attach
1266};
1267
1268#if defined(__NetBSD__)
1269extern struct cfdriver bktr_cd;
1270#else
1271struct cfdriver bktr_cd = {
1272        NULL, "bktr", DV_DULL
1273};
1274#endif
1275
1276int
1277bktr_probe(parent, match, aux)
1278	struct device *parent;
1279#if defined(__OpenBSD__)
1280        void *match;
1281#else
1282        struct cfdata *match;
1283#endif
1284        void *aux;
1285{
1286        struct pci_attach_args *pa = aux;
1287
1288        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
1289            (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
1290             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
1291             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
1292             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
1293                return 1;
1294
1295        return 0;
1296}
1297
1298
1299/*
1300 * the attach routine.
1301 */
1302static void
1303bktr_attach(struct device *parent, struct device *self, void *aux)
1304{
1305	bktr_ptr_t	bktr;
1306	u_long		latency;
1307	u_long		fun;
1308	unsigned int	rev;
1309
1310#if defined(__OpenBSD__)
1311	struct pci_attach_args *pa = aux;
1312	pci_chipset_tag_t pc = pa->pa_pc;
1313
1314	pci_intr_handle_t ih;
1315	const char *intrstr;
1316	int retval;
1317	int unit;
1318
1319	bktr = (bktr_ptr_t)self;
1320	unit = bktr->bktr_dev.dv_unit;
1321
1322	bktr->pc = pa->pa_pc;
1323	bktr->tag = pa->pa_tag;
1324        bktr->dmat = pa->pa_dmat;
1325
1326	/*
1327	 * map memory
1328	 */
1329	bktr->memt = pa->pa_memt;
1330	retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START,
1331			      &bktr->phys_base, &bktr->obmemsz, NULL);
1332	if (!retval)
1333		retval = bus_space_map(pa->pa_memt, bktr->phys_base,
1334				       bktr->obmemsz, 0, &bktr->memh);
1335	if (retval) {
1336		printf(": couldn't map memory\n");
1337		return;
1338	}
1339
1340
1341	/*
1342	 * map interrupt
1343	 */
1344	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
1345			 pa->pa_intrline, &ih)) {
1346		printf(": couldn't map interrupt\n");
1347		return;
1348	}
1349	intrstr = pci_intr_string(pa->pa_pc, ih);
1350
1351	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
1352				      bktr_intr, bktr, bktr->bktr_dev.dv_xname);
1353	if (bktr->ih == NULL) {
1354		printf(": couldn't establish interrupt");
1355		if (intrstr != NULL)
1356			printf(" at %s", intrstr);
1357		printf("\n");
1358		return;
1359	}
1360
1361	if (intrstr != NULL)
1362		printf(": %s\n", intrstr);
1363#endif /* __OpenBSD__ */
1364
1365#if defined(__NetBSD__)
1366	struct pci_attach_args *pa = aux;
1367	pci_intr_handle_t ih;
1368	const char *intrstr;
1369	int retval;
1370	int unit;
1371
1372	bktr = (bktr_ptr_t)self;
1373	unit = bktr->bktr_dev.dv_unit;
1374        bktr->dmat = pa->pa_dmat;
1375
1376	printf("\n");
1377
1378	/*
1379	 * map memory
1380	 */
1381	retval = pci_mapreg_map(pa, PCI_MAPREG_START,
1382				PCI_MAPREG_TYPE_MEM
1383				| PCI_MAPREG_MEM_TYPE_32BIT, 0,
1384				&bktr->memt, &bktr->memh, NULL,
1385				&bktr->obmemsz);
1386	DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n",
1387	     bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz));
1388	if (retval) {
1389		printf("%s: couldn't map memory\n", bktr_name(bktr));
1390		return;
1391	}
1392
1393	/*
1394	 * Disable the brooktree device
1395	 */
1396	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
1397	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
1398
1399	/*
1400	 * map interrupt
1401	 */
1402	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
1403			 pa->pa_intrline, &ih)) {
1404		printf("%s: couldn't map interrupt\n",
1405		       bktr_name(bktr));
1406		return;
1407	}
1408	intrstr = pci_intr_string(pa->pa_pc, ih);
1409	bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
1410				      bktr_intr, bktr);
1411	if (bktr->ih == NULL) {
1412		printf("%s: couldn't establish interrupt",
1413		       bktr_name(bktr));
1414		if (intrstr != NULL)
1415			printf(" at %s", intrstr);
1416		printf("\n");
1417		return;
1418	}
1419	if (intrstr != NULL)
1420		printf("%s: interrupting at %s\n", bktr_name(bktr),
1421		       intrstr);
1422#endif /* __NetBSD__ */
1423
1424/*
1425 * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
1426 * you have more than four, then 16 would probably be a better value.
1427 */
1428#ifndef BROOKTREE_DEF_LATENCY_VALUE
1429#define BROOKTREE_DEF_LATENCY_VALUE	10
1430#endif
1431	latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
1432	latency = (latency >> 8) & 0xff;
1433
1434	if (!latency) {
1435		if (bootverbose) {
1436			printf("%s: PCI bus latency was 0 changing to %d",
1437			       bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
1438		}
1439		latency = BROOKTREE_DEF_LATENCY_VALUE;
1440		pci_conf_write(pa->pa_pc, pa->pa_tag,
1441			       PCI_LATENCY_TIMER, latency<<8);
1442	}
1443
1444
1445	/* Enabled Bus Master
1446	   XXX: check if all old DMA is stopped first (e.g. after warm
1447	   boot) */
1448	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
1449	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
1450		       fun | PCI_COMMAND_MASTER_ENABLE);
1451
1452	/* read the pci id and determine the card type */
1453	fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
1454        rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff;
1455
1456	common_bktr_attach(bktr, unit, fun, rev);
1457}
1458
1459
1460/*
1461 * Special Memory Allocation
1462 */
1463vm_offset_t
1464get_bktr_mem(bktr, dmapp, size)
1465        bktr_ptr_t bktr;
1466        bus_dmamap_t *dmapp;
1467        unsigned int size;
1468{
1469        bus_dma_tag_t dmat = bktr->dmat;
1470        bus_dma_segment_t seg;
1471        bus_size_t align;
1472        int rseg;
1473        caddr_t kva;
1474
1475        /*
1476         * Allocate a DMA area
1477         */
1478        align = 1 << 24;
1479        if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1480                             &rseg, BUS_DMA_NOWAIT)) {
1481                align = PAGE_SIZE;
1482                if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1483                                     &rseg, BUS_DMA_NOWAIT)) {
1484                        printf("%s: Unable to dmamem_alloc of %d bytes\n",
1485			       bktr_name(bktr), size);
1486                        return 0;
1487                }
1488        }
1489        if (bus_dmamem_map(dmat, &seg, rseg, size,
1490                           &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1491                printf("%s: Unable to dmamem_map of %d bytes\n",
1492                        bktr_name(bktr), size);
1493                bus_dmamem_free(dmat, &seg, rseg);
1494                return 0;
1495        }
1496#ifdef __OpenBSD__
1497        bktr->dm_mapsize = size;
1498#endif
1499        /*
1500         * Create and locd the DMA map for the DMA area
1501         */
1502        if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
1503                printf("%s: Unable to dmamap_create of %d bytes\n",
1504                        bktr_name(bktr), size);
1505                bus_dmamem_unmap(dmat, kva, size);
1506                bus_dmamem_free(dmat, &seg, rseg);
1507                return 0;
1508        }
1509        if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
1510                printf("%s: Unable to dmamap_load of %d bytes\n",
1511                        bktr_name(bktr), size);
1512                bus_dmamem_unmap(dmat, kva, size);
1513                bus_dmamem_free(dmat, &seg, rseg);
1514                bus_dmamap_destroy(dmat, *dmapp);
1515                return 0;
1516        }
1517        return (vm_offset_t)kva;
1518}
1519
1520void
1521free_bktr_mem(bktr, dmap, kva)
1522        bktr_ptr_t bktr;
1523        bus_dmamap_t dmap;
1524        vm_offset_t kva;
1525{
1526        bus_dma_tag_t dmat = bktr->dmat;
1527
1528#ifdef __NetBSD__
1529        bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
1530#else
1531        bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize);
1532#endif
1533        bus_dmamem_free(dmat, dmap->dm_segs, 1);
1534        bus_dmamap_destroy(dmat, dmap);
1535}
1536
1537
1538/*---------------------------------------------------------
1539**
1540**	BrookTree 848 character device driver routines
1541**
1542**---------------------------------------------------------
1543*/
1544
1545
1546#define VIDEO_DEV	0x00
1547#define TUNER_DEV	0x01
1548#define VBI_DEV		0x02
1549
1550#define UNIT(x)         (minor((x) & 0x0f))
1551#define FUNCTION(x)     (minor((x >> 4) & 0x0f))
1552
1553/*
1554 *
1555 */
1556int
1557bktr_open(dev_t dev, int flags, int fmt, struct proc *p)
1558{
1559	bktr_ptr_t	bktr;
1560	int		unit;
1561
1562	unit = UNIT(dev);
1563
1564	/* unit out of range */
1565	if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
1566		return(ENXIO);
1567
1568	bktr = bktr_cd.cd_devs[unit];
1569
1570	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1571		return(ENXIO);
1572
1573	switch (FUNCTION(dev)) {
1574	case VIDEO_DEV:
1575		return(video_open(bktr));
1576	case TUNER_DEV:
1577		return(tuner_open(bktr));
1578	case VBI_DEV:
1579		return(vbi_open(bktr));
1580	}
1581
1582	return(ENXIO);
1583}
1584
1585
1586/*
1587 *
1588 */
1589int
1590bktr_close(dev_t dev, int flags, int fmt, struct proc *p)
1591{
1592	bktr_ptr_t	bktr;
1593	int		unit;
1594
1595	unit = UNIT(dev);
1596
1597	bktr = bktr_cd.cd_devs[unit];
1598
1599	switch (FUNCTION(dev)) {
1600	case VIDEO_DEV:
1601		return(video_close(bktr));
1602	case TUNER_DEV:
1603		return(tuner_close(bktr));
1604	case VBI_DEV:
1605		return(vbi_close(bktr));
1606	}
1607
1608	return(ENXIO);
1609}
1610
1611/*
1612 *
1613 */
1614int
1615bktr_read(dev_t dev, struct uio *uio, int ioflag)
1616{
1617	bktr_ptr_t	bktr;
1618	int		unit;
1619
1620	unit = UNIT(dev);
1621
1622	bktr = bktr_cd.cd_devs[unit];
1623
1624	switch (FUNCTION(dev)) {
1625	case VIDEO_DEV:
1626		return(video_read(bktr, unit, dev, uio));
1627	case VBI_DEV:
1628		return(vbi_read(bktr, uio, ioflag));
1629	}
1630
1631        return(ENXIO);
1632}
1633
1634
1635/*
1636 *
1637 */
1638int
1639bktr_write(dev_t dev, struct uio *uio, int ioflag)
1640{
1641	/* operation not supported */
1642	return(EOPNOTSUPP);
1643}
1644
1645/*
1646 *
1647 */
1648int
1649bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr)
1650{
1651	bktr_ptr_t	bktr;
1652	int		unit;
1653
1654	unit = UNIT(dev);
1655
1656	bktr = bktr_cd.cd_devs[unit];
1657
1658	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
1659		return(ENOMEM);
1660
1661	switch (FUNCTION(dev)) {
1662	case VIDEO_DEV:
1663		return(video_ioctl(bktr, unit, cmd, arg, pr));
1664	case TUNER_DEV:
1665		return(tuner_ioctl(bktr, unit, cmd, arg, pr));
1666	}
1667
1668	return(ENXIO);
1669}
1670
1671/*
1672 *
1673 */
1674paddr_t
1675bktr_mmap(dev_t dev, off_t offset, int nprot)
1676{
1677	int		unit;
1678	bktr_ptr_t	bktr;
1679
1680	unit = UNIT(dev);
1681
1682	if (FUNCTION(dev) > 0)	/* only allow mmap on /dev/bktr[n] */
1683		return(-1);
1684
1685	bktr = bktr_cd.cd_devs[unit];
1686
1687	if ((vaddr_t)offset < 0)
1688		return(-1);
1689
1690	if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
1691		return(-1);
1692
1693#ifdef __NetBSD__
1694	return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
1695				(vaddr_t)offset, nprot, BUS_DMA_WAITOK));
1696#else
1697	return(i386_btop(vtophys(bktr->bigbuf) + offset));
1698#endif
1699}
1700
1701#endif /* __NetBSD__ || __OpenBSD__ */
1702