xref: /dragonfly/sys/dev/video/bktr/bktr_os.c (revision 20b08a9afb666038efdd560d9510336d9928c3bb)
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 );
bktr_intr(void * arg)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
bktr_probe(device_t dev)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
bktr_attach(device_t dev)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
bktr_detach(device_t dev)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
bktr_shutdown(device_t dev)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
get_bktr_mem(int unit,unsigned size)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
bktr_open(struct dev_open_args * ap)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
bktr_close(struct dev_close_args * ap)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
bktr_read(struct dev_read_args * ap)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
bktr_write(struct dev_write_args * ap)605 bktr_write(struct dev_write_args *ap)
606 {
607           return( EINVAL ); /* XXX or ENXIO ? */
608 }
609 
610 
611 /*
612  *
613  */
614 static int
bktr_ioctl(struct dev_ioctl_args * ap)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
bktr_mmap(struct dev_mmap_args * ap)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
bktr_kqfilter(struct dev_kqfilter_args * ap)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
bktr_filter_detach(struct knote * kn)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
bktr_filter(struct knote * kn,long hint)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