Merge commit 'origin/vendor/PAM_PASSWDQC'
[dragonfly.git] / sys / dev / video / bktr / bktr_os.c
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         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 }