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