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