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