xref: /dragonfly/sys/dev/video/bktr/bktr_os.c (revision 8a7bdfea)
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.20 2007/11/13 19:43:32 swildner 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 (usefull 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 	dev_ops_add(&bktr_ops, 0x0f, unit);
355 	make_dev(&bktr_ops, unit,    0, 0, 0444, "bktr%d",  unit);
356 	make_dev(&bktr_ops, unit+16, 0, 0, 0444, "tuner%d", unit);
357 	make_dev(&bktr_ops, unit+32, 0, 0, 0444, "vbi%d"  , unit);
358 
359 
360 	return 0;
361 
362 fail:
363 	if (bktr->res_irq)
364 		bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
365 	if (bktr->res_mem)
366 		bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem);
367 	return error;
368 
369 }
370 
371 /*
372  * the detach routine.
373  */
374 static int
375 bktr_detach( device_t dev )
376 {
377 	struct bktr_softc *bktr = device_get_softc(dev);
378 
379 #ifdef BKTR_NEW_MSP34XX_DRIVER
380 	/* Disable the soundchip and kernel thread */
381 	if (bktr->msp3400c_info != NULL)
382 		msp_detach(bktr);
383 #endif
384 
385 	/* Disable the brooktree device */
386 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
387 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
388 
389 #if defined(BKTR_USE_FREEBSD_SMBUS)
390 	if (bt848_i2c_detach(dev))
391 		kprintf("bktr%d: i2c_attach: can't attach\n",
392 		     device_get_unit(dev));
393 #endif
394 #ifdef USE_VBIMUTEX
395         mtx_destroy(&bktr->vbimutex);
396 #endif
397 
398 	/* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */
399 	/* The memory is retained by the bktr_mem module so we can unload and */
400 	/* then reload the main bktr driver module */
401 
402 	/* removing the ops automatically destroys all related devices */
403 	dev_ops_remove(&bktr_ops, 0x0f, device_get_unit(dev));
404 
405 	/*
406 	 * Deallocate resources.
407 	 */
408 	bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
409 	bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
410 	bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
411 
412 	return 0;
413 }
414 
415 /*
416  * the shutdown routine.
417  */
418 static int
419 bktr_shutdown( device_t dev )
420 {
421 	struct bktr_softc *bktr = device_get_softc(dev);
422 
423 	/* Disable the brooktree device */
424 	OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
425 	OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
426 
427 	return 0;
428 }
429 
430 
431 /*
432  * Special Memory Allocation
433  */
434 vm_offset_t
435 get_bktr_mem( int unit, unsigned size )
436 {
437 	vm_offset_t	addr = 0;
438 
439 	addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0,
440 	    0xffffffff, 1<<24, 0);
441 	if (addr == 0)
442 		addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0,
443 		    0xffffffff, PAGE_SIZE, 0);
444 	if (addr == 0) {
445 		kprintf("bktr%d: Unable to allocate %d bytes of memory.\n",
446 			unit, size);
447 	}
448 
449 	return( addr );
450 }
451 
452 
453 /*---------------------------------------------------------
454 **
455 **	BrookTree 848 character device driver routines
456 **
457 **---------------------------------------------------------
458 */
459 
460 #define VIDEO_DEV	0x00
461 #define TUNER_DEV	0x01
462 #define VBI_DEV		0x02
463 
464 #define UNIT(x)		((x) & 0x0f)
465 #define FUNCTION(x)	(x >> 4)
466 
467 /*
468  *
469  */
470 static int
471 bktr_open(struct dev_open_args *ap)
472 {
473 	cdev_t dev = ap->a_head.a_dev;
474 	bktr_ptr_t	bktr;
475 	int		unit;
476 	int		result;
477 
478 	unit = UNIT( minor(dev) );
479 
480 	/* Get the device data */
481 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
482 	if (bktr == NULL) {
483 		/* the device is no longer valid/functioning */
484 		return (ENXIO);
485 	}
486 
487 	if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
488 		return( ENXIO );
489 
490 	/* Record that the device is now busy */
491 	device_busy(devclass_get_device(bktr_devclass, unit));
492 
493 
494 	if (bt848_card != -1) {
495 	  if ((bt848_card >> 8   == unit ) &&
496 	     ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
497 	    if ( bktr->bt848_card != (bt848_card & 0xff) ) {
498 	      bktr->bt848_card = (bt848_card & 0xff);
499 	      probeCard(bktr, FALSE, unit);
500 	    }
501 	  }
502 	}
503 
504 	if (bt848_tuner != -1) {
505 	  if ((bt848_tuner >> 8   == unit ) &&
506 	     ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
507 	    if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
508 	      bktr->bt848_tuner = (bt848_tuner & 0xff);
509 	      probeCard(bktr, FALSE, unit);
510 	    }
511 	  }
512 	}
513 
514 	if (bt848_reverse_mute != -1) {
515 	  if ((bt848_reverse_mute >> 8)   == unit ) {
516 	    bktr->reverse_mute = bt848_reverse_mute & 0xff;
517 	  }
518 	}
519 
520 	if (bt848_slow_msp_audio != -1) {
521 	  if ((bt848_slow_msp_audio >> 8) == unit ) {
522 	      bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
523 	  }
524 	}
525 
526 #ifdef BKTR_NEW_MSP34XX_DRIVER
527 	if (bt848_stereo_once != 0) {
528 	  if ((bt848_stereo_once >> 8) == unit ) {
529 	      bktr->stereo_once = (bt848_stereo_once & 0xff);
530 	  }
531 	}
532 
533 	if (bt848_amsound != -1) {
534 	  if ((bt848_amsound >> 8) == unit ) {
535 	      bktr->amsound = (bt848_amsound & 0xff);
536 	  }
537 	}
538 
539 	if (bt848_dolby != -1) {
540 	  if ((bt848_dolby >> 8) == unit ) {
541 	      bktr->dolby = (bt848_dolby & 0xff);
542 	  }
543 	}
544 #endif
545 
546 	switch ( FUNCTION( minor(dev) ) ) {
547 	case VIDEO_DEV:
548 		result = video_open( bktr );
549 		break;
550 	case TUNER_DEV:
551 		result = tuner_open( bktr );
552 		break;
553 	case VBI_DEV:
554 		result = vbi_open( bktr );
555 		break;
556 	default:
557 		result = ENXIO;
558 		break;
559 	}
560 
561 	/* If there was an error opening the device, undo the busy status */
562 	if (result != 0)
563 		device_unbusy(devclass_get_device(bktr_devclass, unit));
564 	return( result );
565 }
566 
567 
568 /*
569  *
570  */
571 static int
572 bktr_close(struct dev_close_args *ap)
573 {
574 	cdev_t dev = ap->a_head.a_dev;
575 	bktr_ptr_t	bktr;
576 	int		unit;
577 	int		result;
578 
579 	unit = UNIT( minor(dev) );
580 
581 	/* Get the device data */
582 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
583 	if (bktr == NULL) {
584 		/* the device is no longer valid/functioning */
585 		return (ENXIO);
586 	}
587 
588 	switch ( FUNCTION( minor(dev) ) ) {
589 	case VIDEO_DEV:
590 		result = video_close( bktr );
591 		break;
592 	case TUNER_DEV:
593 		result = tuner_close( bktr );
594 		break;
595 	case VBI_DEV:
596 		result = vbi_close( bktr );
597 		break;
598 	default:
599 		return (ENXIO);
600 		break;
601 	}
602 
603 	device_unbusy(devclass_get_device(bktr_devclass, unit));
604 	return( result );
605 }
606 
607 
608 /*
609  *
610  */
611 static int
612 bktr_read(struct dev_read_args *ap)
613 {
614 	cdev_t dev = ap->a_head.a_dev;
615 	bktr_ptr_t	bktr;
616 	int		unit;
617 
618 	unit = UNIT(minor(dev));
619 
620 	/* Get the device data */
621 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
622 	if (bktr == NULL) {
623 		/* the device is no longer valid/functioning */
624 		return (ENXIO);
625 	}
626 
627 	switch ( FUNCTION( minor(dev) ) ) {
628 	case VIDEO_DEV:
629 		return( video_read( bktr, unit, dev, ap->a_uio ) );
630 	case VBI_DEV:
631 		return( vbi_read( bktr, ap->a_uio, ap->a_ioflag ) );
632 	}
633         return( ENXIO );
634 }
635 
636 
637 /*
638  *
639  */
640 static int
641 bktr_write(struct dev_write_args *ap)
642 {
643 	return( EINVAL ); /* XXX or ENXIO ? */
644 }
645 
646 
647 /*
648  *
649  */
650 static int
651 bktr_ioctl(struct dev_ioctl_args *ap)
652 {
653 	cdev_t dev = ap->a_head.a_dev;
654 	u_long cmd = ap->a_cmd;
655 	bktr_ptr_t	bktr;
656 	int		unit;
657 
658 	unit = UNIT(minor(dev));
659 
660 	/* Get the device data */
661 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
662 	if (bktr == NULL) {
663 		/* the device is no longer valid/functioning */
664 		return (ENXIO);
665 	}
666 
667 #ifdef BKTR_GPIO_ACCESS
668 	if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN &&
669 	    cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA &&
670 	    cmd != BT848_GPIO_SET_DATA)	/* no frame buffer allocated (ioctl failed) */
671 		return( ENOMEM );
672 #else
673 	if (bktr->bigbuf == 0)	/* no frame buffer allocated (ioctl failed) */
674 		return( ENOMEM );
675 #endif
676 
677 	switch ( FUNCTION( minor(dev) ) ) {
678 	case VIDEO_DEV:
679 		return( video_ioctl( bktr, unit, cmd, ap->a_data, curthread ) );
680 	case TUNER_DEV:
681 		return( tuner_ioctl( bktr, unit, cmd, ap->a_data, curthread ) );
682 	}
683 
684 	return( ENXIO );
685 }
686 
687 
688 /*
689  *
690  */
691 static int
692 bktr_mmap(struct dev_mmap_args *ap)
693 {
694 	cdev_t dev = ap->a_head.a_dev;
695 	int		unit;
696 	bktr_ptr_t	bktr;
697 
698 	unit = UNIT(minor(dev));
699 
700 	if (FUNCTION(minor(dev)) > 0)	/* only allow mmap on /dev/bktr[n] */
701 		return(EINVAL);
702 
703 	/* Get the device data */
704 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
705 	if (bktr == NULL) {
706 		/* the device is no longer valid/functioning */
707 		return (ENXIO);
708 	}
709 
710 	if (ap->a_nprot & PROT_EXEC)
711 		return(EINVAL);
712 
713 	if (ap->a_offset < 0)
714 		return(EINVAL);
715 
716 	if (ap->a_offset >= bktr->alloc_pages * PAGE_SIZE)
717 		return(EINVAL);
718 
719 	ap->a_result = atop(vtophys(bktr->bigbuf) + ap->a_offset);
720 	return(0);
721 }
722 
723 static int
724 bktr_poll(struct dev_poll_args *ap)
725 {
726 	cdev_t dev = ap->a_head.a_dev;
727 	int		unit;
728 	bktr_ptr_t	bktr;
729 	int revents = 0;
730 
731 	unit = UNIT(minor(dev));
732 
733 	/* Get the device data */
734 	bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
735 	if (bktr == NULL) {
736 		/* the device is no longer valid/functioning */
737 		return (ENXIO);
738 	}
739 
740 	LOCK_VBI(bktr);
741 	crit_enter();
742 
743 	if (ap->a_events & (POLLIN | POLLRDNORM)) {
744 
745 		switch ( FUNCTION( minor(dev) ) ) {
746 		case VBI_DEV:
747 			if(bktr->vbisize == 0)
748 				selrecord(curthread, &bktr->vbi_select);
749 			else
750 				revents |= ap->a_events & (POLLIN | POLLRDNORM);
751 			break;
752 		}
753 	}
754 
755 	crit_exit();
756 	UNLOCK_VBI(bktr);
757 
758 	ap->a_events = revents;
759 	return (0);
760 }
761