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