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