xref: /dragonfly/sys/dev/video/bktr/bktr_os.c (revision 7ff0fc30)
1 /*-
2  * 1. Redistributions of source code must retain the
3  * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Amancio Hasty and
17  *      Roger Hardiman
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * $FreeBSD: src/sys/dev/bktr/bktr_os.c,v 1.54 2007/02/23 12:18:34 piso Exp $
34  */
35 
36 /*
37  * This is part of the Driver for Video Capture Cards (Frame grabbers)
38  * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
39  * chipset.
40  * Copyright Roger Hardiman and Amancio Hasty.
41  *
42  * bktr_os : This has all the Operating System dependant code,
43  *             probe/attach and open/close/ioctl/read/mmap
44  *             memory allocation
45  *             PCI bus interfacing
46  */
47 
48 #include "opt_bktr.h"		/* include any kernel config options */
49 
50 #define FIFO_RISC_DISABLED      0
51 #define ALL_INTS_DISABLED       0
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/conf.h>
56 #include <sys/device.h>
57 #include <sys/uio.h>
58 #include <sys/kernel.h>
59 #include <sys/signalvar.h>
60 #include <sys/malloc.h>
61 #include <sys/mman.h>
62 #include <sys/event.h>
63 #include <sys/bus.h>
64 #include <sys/rman.h>
65 #include <sys/thread2.h>
66 
67 #include <vm/vm.h>
68 #include <vm/vm_kern.h>
69 #include <vm/pmap.h>
70 #include <vm/vm_extern.h>
71 
72 #include <bus/pci/pcivar.h>
73 #include <bus/pci/pcireg.h>
74 #include "pcidevs.h"
75 
76 #include <sys/sysctl.h>
77 int bt848_card = -1;
78 int bt848_tuner = -1;
79 int bt848_reverse_mute = -1;
80 int bt848_format = -1;
81 int bt848_slow_msp_audio = -1;
82 #ifdef BKTR_NEW_MSP34XX_DRIVER
83 int bt848_stereo_once = 0;	/* no continuous stereo monitoring */
84 int bt848_amsound = 0;		/* hard-wire AM sound at 6.5 Hz (france),
85 				   the autoscan seems work well only with FM... */
86 int bt848_dolby = 0;
87 #endif
88 
89 SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
90 SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
91 SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
92 SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
93 SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
94 SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
95 #ifdef BKTR_NEW_MSP34XX_DRIVER
96 SYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, "");
97 SYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, "");
98 SYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, "");
99 #endif
100 
101 #include <dev/video/meteor/ioctl_meteor.h>
102 #include <dev/video/bktr/ioctl_bt848.h>	/* extensions to ioctl_meteor.h */
103 #include <dev/video/bktr/bktr_reg.h>
104 #include <dev/video/bktr/bktr_tuner.h>
105 #include <dev/video/bktr/bktr_card.h>
106 #include <dev/video/bktr/bktr_audio.h>
107 #include <dev/video/bktr/bktr_core.h>
108 #include <dev/video/bktr/bktr_os.h>
109 
110 static int	bktr_probe( device_t dev );
111 static int	bktr_attach( device_t dev );
112 static int	bktr_detach( device_t dev );
113 static int	bktr_shutdown( device_t dev );
114 static void	bktr_intr(void *arg) { common_bktr_intr(arg); }
115 
116 static device_method_t bktr_methods[] = {
117 	/* Device interface */
118 	DEVMETHOD(device_probe,         bktr_probe),
119 	DEVMETHOD(device_attach,        bktr_attach),
120 	DEVMETHOD(device_detach,        bktr_detach),
121 	DEVMETHOD(device_shutdown,      bktr_shutdown),
122 
123 	DEVMETHOD_END
124 };
125 
126 static driver_t bktr_driver = {
127 	"bktr",
128 	bktr_methods,
129 	sizeof(struct bktr_softc),
130 };
131 
132 static devclass_t bktr_devclass;
133 
134 static	d_open_t	bktr_open;
135 static	d_close_t	bktr_close;
136 static	d_read_t	bktr_read;
137 static	d_write_t	bktr_write;
138 static	d_ioctl_t	bktr_ioctl;
139 static	d_mmap_t	bktr_mmap;
140 static	d_kqfilter_t	bktr_kqfilter;
141 
142 static void bktr_filter_detach(struct knote *);
143 static int bktr_filter(struct knote *, long);
144 
145 static struct dev_ops bktr_ops = {
146 	{ "bktr", 0, 0 },
147 	.d_open =	bktr_open,
148 	.d_close =	bktr_close,
149 	.d_read =	bktr_read,
150 	.d_write =	bktr_write,
151 	.d_ioctl =	bktr_ioctl,
152 	.d_kqfilter =	bktr_kqfilter,
153 	.d_mmap =	bktr_mmap,
154 };
155 
156 DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, NULL, NULL);
157 MODULE_DEPEND(bktr, bktr_mem, 1,1,1);
158 MODULE_VERSION(bktr, 1);
159 
160 /*
161  * the boot time probe routine.
162  */
163 static int
164 bktr_probe( device_t dev )
165 {
166 	unsigned int type = pci_get_devid(dev);
167         unsigned int rev  = pci_get_revid(dev);
168 
169 	if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
170 	{
171 		switch (PCI_PRODUCT(type)) {
172 		case PCI_PRODUCT_BROOKTREE_BT848:
173 			if (rev == 0x12)
174 				device_set_desc(dev, "BrookTree 848A");
175 			else
176 				device_set_desc(dev, "BrookTree 848");
177 			return BUS_PROBE_DEFAULT;
178 		case PCI_PRODUCT_BROOKTREE_BT849:
179 			device_set_desc(dev, "BrookTree 849A");
180 			return BUS_PROBE_DEFAULT;
181 		case PCI_PRODUCT_BROOKTREE_BT878:
182 			device_set_desc(dev, "BrookTree 878");
183 			return BUS_PROBE_DEFAULT;
184 		case PCI_PRODUCT_BROOKTREE_BT879:
185 			device_set_desc(dev, "BrookTree 879");
186 			return BUS_PROBE_DEFAULT;
187 		}
188 	}
189 
190         return ENXIO;
191 }
192 
193 
194 /*
195  * the attach routine.
196  */
197 static int
198 bktr_attach( device_t dev )
199 {
200 	u_long		latency;
201 	u_long		fun;
202 	u_long		val;
203 	unsigned int	rev;
204 	unsigned int	unit;
205 	int		error = 0;
206 #ifdef BROOKTREE_IRQ
207 	u_long		old_irq, new_irq;
208 #endif
209 
210         struct bktr_softc *bktr = device_get_softc(dev);
211 
212 	unit = device_get_unit(dev);
213 
214 	/* build the device name for bktr_name() */
215 	ksnprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
216 
217 	/*
218 	 * Enable bus mastering and Memory Mapped device
219 	 */
220 	val = pci_read_config(dev, PCIR_COMMAND, 4);
221 	val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
222 	pci_write_config(dev, PCIR_COMMAND, val, 4);
223 
224 	/*
225 	 * Map control/status registers.
226 	 */
227 	bktr->mem_rid = PCIR_BAR(0);
228 	bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
229 					&bktr->mem_rid, RF_ACTIVE);
230 
231 	if (!bktr->res_mem) {
232 		device_printf(dev, "could not map memory\n");
233 		error = ENXIO;
234 		goto fail;
235 	}
236 	bktr->memt = rman_get_bustag(bktr->res_mem);
237 	bktr->memh = rman_get_bushandle(bktr->res_mem);
238 
239 
240 	/*
241 	 * Disable the brooktree device
242 	 */
243 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
244 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
245 
246 
247 #ifdef BROOKTREE_IRQ		/* from the configuration file */
248 	old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
249 	pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
250 	new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
251 	kprintf("bktr%d: attach: irq changed from %d to %d\n",
252 		unit, (old_irq & 0xff), (new_irq & 0xff));
253 #endif
254 
255 	/*
256 	 * Allocate our interrupt.
257 	 */
258 	bktr->irq_rid = 0;
259 	bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
260 				&bktr->irq_rid, RF_SHAREABLE | RF_ACTIVE);
261 	if (bktr->res_irq == NULL) {
262 		device_printf(dev, "could not map interrupt\n");
263 		error = ENXIO;
264 		goto fail;
265 	}
266 
267 	error = bus_setup_intr(dev, bktr->res_irq, 0,
268                                bktr_intr, bktr, &bktr->res_ih, NULL);
269 	if (error) {
270 		device_printf(dev, "could not setup irq\n");
271 		goto fail;
272 
273 	}
274 
275 
276 	/* Update the Device Control Register */
277 	/* on Bt878 and Bt879 cards           */
278 	fun = pci_read_config( dev, 0x40, 2);
279         fun = fun | 1;	/* Enable writes to the sub-system vendor ID */
280 
281 #if defined( BKTR_430_FX_MODE )
282 	if (bootverbose) kprintf("Using 430 FX chipset compatibility mode\n");
283         fun = fun | 2;	/* Enable Intel 430 FX compatibility mode */
284 #endif
285 
286 #if defined( BKTR_SIS_VIA_MODE )
287 	if (bootverbose) kprintf("Using SiS/VIA chipset compatibility mode\n");
288         fun = fun | 4;	/* Enable SiS/VIA compatibility mode (useful for
289                            OPTi chipset motherboards too */
290 #endif
291 	pci_write_config(dev, 0x40, fun, 2);
292 
293 /*
294  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
295  * you have more than four, then 16 would probably be a better value.
296  */
297 #ifndef BROOKTREE_DEF_LATENCY_VALUE
298 #define BROOKTREE_DEF_LATENCY_VALUE	10
299 #endif
300 	latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4);
301 	latency = (latency >> 8) & 0xff;
302 	if ( bootverbose ) {
303 		if (latency)
304 			kprintf("brooktree%d: PCI bus latency is", unit);
305 		else
306 			kprintf("brooktree%d: PCI bus latency was 0 changing to",
307 				unit);
308 	}
309 	if ( !latency ) {
310 		latency = BROOKTREE_DEF_LATENCY_VALUE;
311 		pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4);
312 	}
313 	if ( bootverbose ) {
314 		kprintf(" %d.\n", (int) latency);
315 	}
316 
317 	/* read the pci device id and revision id */
318 	fun = pci_get_devid(dev);
319         rev = pci_get_revid(dev);
320 
321 	/* call the common attach code */
322 	common_bktr_attach( bktr, unit, fun, rev );
323 
324 	/* make the device entries */
325 	make_dev(&bktr_ops, unit,    0, 0, 0444, "bktr%d",  unit);
326 	make_dev(&bktr_ops, unit+16, 0, 0, 0444, "tuner%d", unit);
327 	make_dev(&bktr_ops, unit+32, 0, 0, 0444, "vbi%d"  , unit);
328 
329 	return 0;
330 
331 fail:
332 	if (bktr->res_irq)
333 		bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
334 	if (bktr->res_mem)
335 		bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem);
336 	return error;
337 
338 }
339 
340 /*
341  * the detach routine.
342  */
343 static int
344 bktr_detach( device_t dev )
345 {
346 	struct bktr_softc *bktr = device_get_softc(dev);
347 
348 #ifdef BKTR_NEW_MSP34XX_DRIVER
349 	/* Disable the soundchip and kernel thread */
350 	if (bktr->msp3400c_info != NULL)
351 		msp_detach(bktr);
352 #endif
353 
354 	/* Disable the brooktree device */
355 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
356 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
357 
358 #ifdef USE_VBIMUTEX
359         mtx_destroy(&bktr->vbimutex);
360 #endif
361 
362 	/* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */
363 	/* The memory is retained by the bktr_mem module so we can unload and */
364 	/* then reload the main bktr driver module */
365 
366 	/* removing the ops automatically destroys all related devices */
367 	dev_ops_remove_minor(&bktr_ops, /*0x0f, */device_get_unit(dev));
368 
369 	/*
370 	 * Deallocate resources.
371 	 */
372 	bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
373 	bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
374 	bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
375 
376 	return 0;
377 }
378 
379 /*
380  * the shutdown routine.
381  */
382 static int
383 bktr_shutdown( device_t dev )
384 {
385 	struct bktr_softc *bktr = device_get_softc(dev);
386 
387 	/* Disable the brooktree device */
388 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
389 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
390 
391 	return 0;
392 }
393 
394 
395 /*
396  * Special Memory Allocation
397  */
398 vm_offset_t
399 get_bktr_mem( int unit, unsigned size )
400 {
401 	vm_offset_t	addr = 0;
402 
403 	addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0,
404 	    0xffffffff, 1<<24, 0);
405 	if (addr == 0)
406 		addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0,
407 		    0xffffffff, PAGE_SIZE, 0);
408 	if (addr == 0) {
409 		kprintf("bktr%d: Unable to allocate %d bytes of memory.\n",
410 			unit, size);
411 	}
412 
413 	return( addr );
414 }
415 
416 
417 /*---------------------------------------------------------
418 **
419 **	BrookTree 848 character device driver routines
420 **
421 **---------------------------------------------------------
422 */
423 
424 #define VIDEO_DEV	0x00
425 #define TUNER_DEV	0x01
426 #define VBI_DEV		0x02
427 
428 #define UNIT(x)		((x) & 0x0f)
429 #define FUNCTION(x)	(x >> 4)
430 
431 /*
432  *
433  */
434 static int
435 bktr_open(struct dev_open_args *ap)
436 {
437 	cdev_t dev = ap->a_head.a_dev;
438 	bktr_ptr_t	bktr;
439 	int		unit;
440 	int		result;
441 
442 	unit = UNIT( minor(dev) );
443 
444 	/* Get the device data */
445 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
446 	if (bktr == NULL) {
447 		/* the device is no longer valid/functioning */
448 		return (ENXIO);
449 	}
450 
451 	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
452 		return( ENXIO );
453 
454 	/* Record that the device is now busy */
455 	device_busy(devclass_get_device(bktr_devclass, unit));
456 
457 
458 	if (bt848_card != -1) {
459 	  if ((bt848_card >> 8   == unit ) &&
460 	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
461 	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
462 	      bktr->bt848_card = (bt848_card & 0xff);
463 	      probeCard(bktr, FALSE, unit);
464 	    }
465 	  }
466 	}
467 
468 	if (bt848_tuner != -1) {
469 	  if ((bt848_tuner >> 8   == unit ) &&
470 	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
471 	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
472 	      bktr->bt848_tuner = (bt848_tuner & 0xff);
473 	      probeCard(bktr, FALSE, unit);
474 	    }
475 	  }
476 	}
477 
478 	if (bt848_reverse_mute != -1) {
479 	  if ((bt848_reverse_mute >> 8)   == unit ) {
480 	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
481 	  }
482 	}
483 
484 	if (bt848_slow_msp_audio != -1) {
485 	  if ((bt848_slow_msp_audio >> 8) == unit ) {
486 	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
487 	  }
488 	}
489 
490 #ifdef BKTR_NEW_MSP34XX_DRIVER
491 	if (bt848_stereo_once != 0) {
492 	  if ((bt848_stereo_once >> 8) == unit ) {
493 	      bktr->stereo_once = (bt848_stereo_once & 0xff);
494 	  }
495 	}
496 
497 	if (bt848_amsound != -1) {
498 	  if ((bt848_amsound >> 8) == unit ) {
499 	      bktr->amsound = (bt848_amsound & 0xff);
500 	  }
501 	}
502 
503 	if (bt848_dolby != -1) {
504 	  if ((bt848_dolby >> 8) == unit ) {
505 	      bktr->dolby = (bt848_dolby & 0xff);
506 	  }
507 	}
508 #endif
509 
510 	switch ( FUNCTION( minor(dev) ) ) {
511 	case VIDEO_DEV:
512 		result = video_open( bktr );
513 		break;
514 	case TUNER_DEV:
515 		result = tuner_open( bktr );
516 		break;
517 	case VBI_DEV:
518 		result = vbi_open( bktr );
519 		break;
520 	default:
521 		result = ENXIO;
522 		break;
523 	}
524 
525 	/* If there was an error opening the device, undo the busy status */
526 	if (result != 0)
527 		device_unbusy(devclass_get_device(bktr_devclass, unit));
528 	return( result );
529 }
530 
531 
532 /*
533  *
534  */
535 static int
536 bktr_close(struct dev_close_args *ap)
537 {
538 	cdev_t dev = ap->a_head.a_dev;
539 	bktr_ptr_t	bktr;
540 	int		unit;
541 	int		result;
542 
543 	unit = UNIT( minor(dev) );
544 
545 	/* Get the device data */
546 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
547 	if (bktr == NULL) {
548 		/* the device is no longer valid/functioning */
549 		return (ENXIO);
550 	}
551 
552 	switch ( FUNCTION( minor(dev) ) ) {
553 	case VIDEO_DEV:
554 		result = video_close( bktr );
555 		break;
556 	case TUNER_DEV:
557 		result = tuner_close( bktr );
558 		break;
559 	case VBI_DEV:
560 		result = vbi_close( bktr );
561 		break;
562 	default:
563 		return (ENXIO);
564 		break;
565 	}
566 
567 	device_unbusy(devclass_get_device(bktr_devclass, unit));
568 	return( result );
569 }
570 
571 
572 /*
573  *
574  */
575 static int
576 bktr_read(struct dev_read_args *ap)
577 {
578 	cdev_t dev = ap->a_head.a_dev;
579 	bktr_ptr_t	bktr;
580 	int		unit;
581 
582 	unit = UNIT(minor(dev));
583 
584 	/* Get the device data */
585 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
586 	if (bktr == NULL) {
587 		/* the device is no longer valid/functioning */
588 		return (ENXIO);
589 	}
590 
591 	switch ( FUNCTION( minor(dev) ) ) {
592 	case VIDEO_DEV:
593 		return( video_read( bktr, unit, dev, ap->a_uio ) );
594 	case VBI_DEV:
595 		return( vbi_read( bktr, ap->a_uio, ap->a_ioflag ) );
596 	}
597         return( ENXIO );
598 }
599 
600 
601 /*
602  *
603  */
604 static int
605 bktr_write(struct dev_write_args *ap)
606 {
607 	return( EINVAL ); /* XXX or ENXIO ? */
608 }
609 
610 
611 /*
612  *
613  */
614 static int
615 bktr_ioctl(struct dev_ioctl_args *ap)
616 {
617 	cdev_t dev = ap->a_head.a_dev;
618 	u_long cmd = ap->a_cmd;
619 	bktr_ptr_t	bktr;
620 	int		unit;
621 
622 	unit = UNIT(minor(dev));
623 
624 	/* Get the device data */
625 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
626 	if (bktr == NULL) {
627 		/* the device is no longer valid/functioning */
628 		return (ENXIO);
629 	}
630 
631 #ifdef BKTR_GPIO_ACCESS
632 	if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN &&
633 	    cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA &&
634 	    cmd != BT848_GPIO_SET_DATA)	/* no frame buffer allocated (ioctl failed) */
635 		return( ENOMEM );
636 #else
637 	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
638 		return( ENOMEM );
639 #endif
640 
641 	switch ( FUNCTION( minor(dev) ) ) {
642 	case VIDEO_DEV:
643 		return( video_ioctl( bktr, unit, cmd, ap->a_data, curthread ) );
644 	case TUNER_DEV:
645 		return( tuner_ioctl( bktr, unit, cmd, ap->a_data, curthread ) );
646 	}
647 
648 	return( ENXIO );
649 }
650 
651 
652 /*
653  *
654  */
655 static int
656 bktr_mmap(struct dev_mmap_args *ap)
657 {
658 	cdev_t dev = ap->a_head.a_dev;
659 	int		unit;
660 	bktr_ptr_t	bktr;
661 
662 	unit = UNIT(minor(dev));
663 
664 	if (FUNCTION(minor(dev)) > 0)	/* only allow mmap on /dev/bktr[n] */
665 		return(EINVAL);
666 
667 	/* Get the device data */
668 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
669 	if (bktr == NULL) {
670 		/* the device is no longer valid/functioning */
671 		return (ENXIO);
672 	}
673 
674 	if (ap->a_nprot & PROT_EXEC)
675 		return(EINVAL);
676 
677 	if (ap->a_offset < 0)
678 		return(EINVAL);
679 
680 	if (ap->a_offset >= bktr->alloc_pages * PAGE_SIZE)
681 		return(EINVAL);
682 
683 	ap->a_result = atop(vtophys(bktr->bigbuf) + ap->a_offset);
684 	return(0);
685 }
686 
687 static struct filterops bktr_filterops =
688 	{ FILTEROP_ISFD, NULL, bktr_filter_detach, bktr_filter };
689 
690 static int
691 bktr_kqfilter(struct dev_kqfilter_args *ap)
692 {
693 	cdev_t dev = ap->a_head.a_dev;
694 	struct knote *kn = ap->a_kn;
695 	struct klist *klist;
696 	bktr_ptr_t bktr;
697 	int unit;
698 
699 	ap->a_result = 0;
700 
701 	switch (kn->kn_filter) {
702 	case EVFILT_READ:
703 		if (FUNCTION(minor(dev)) == VBI_DEV) {
704 			unit = UNIT(minor(dev));
705 			/* Get the device data */
706 			bktr = (struct bktr_softc *)
707 			    devclass_get_softc(bktr_devclass, unit);
708 			kn->kn_fop = &bktr_filterops;
709 			kn->kn_hook = (caddr_t)bktr;
710 			break;
711 		}
712 		/* fall through */
713 	default:
714 		ap->a_result = EOPNOTSUPP;
715 		return (0);
716 	}
717 
718 	klist = &bktr->vbi_kq.ki_note;
719 	knote_insert(klist, kn);
720 
721 	return (0);
722 }
723 
724 static void
725 bktr_filter_detach(struct knote *kn)
726 {
727 	bktr_ptr_t bktr = (bktr_ptr_t)kn->kn_hook;
728 	struct klist *klist;
729 
730 	klist = &bktr->vbi_kq.ki_note;
731 	knote_insert(klist, kn);
732 }
733 
734 static int
735 bktr_filter(struct knote *kn, long hint)
736 {
737 	bktr_ptr_t bktr = (bktr_ptr_t)kn->kn_hook;
738 	int ready = 0;
739 
740 	if (bktr == NULL) {
741 		/* the device is no longer valid/functioning */
742 		kn->kn_flags |= (EV_EOF | EV_NODATA);
743 		return (1);
744 	}
745 
746 	LOCK_VBI(bktr);
747 	crit_enter();
748 	if (bktr->vbisize != 0)
749 		ready = 1;
750 	crit_exit();
751 	UNLOCK_VBI(bktr);
752 
753 	return (ready);
754 }
755