proc->thread stage 2: MAJOR revamping of system calls, ucred, jail API,
[dragonfly.git] / sys / dev / video / bktr / bktr_os.c
1 /* $FreeBSD: src/sys/dev/bktr/bktr_os.c,v 1.4.2.3 2000/10/27 00:46:09 jhb Exp $ */
2 /* $DragonFly: src/sys/dev/video/bktr/bktr_os.c,v 1.3 2003/06/23 17:55:30 dillon Exp $ */
3
4 /*
5  * This is part of the Driver for Video Capture Cards (Frame grabbers)
6  * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
7  * chipset.
8  * Copyright Roger Hardiman and Amancio Hasty.
9  *
10  * bktr_os : This has all the Operating System dependant code,
11  *             probe/attach and open/close/ioctl/read/mmap
12  *             memory allocation
13  *             PCI bus interfacing
14  *             
15  *
16  */
17
18 /*
19  * 1. Redistributions of source code must retain the 
20  * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
21  * All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the above copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *      This product includes software developed by Amancio Hasty and
34  *      Roger Hardiman
35  * 4. The name of the author may not be used to endorse or promote products 
36  *    derived from this software without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
40  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
44  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
47  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  */
50
51
52 #ifdef __FreeBSD__
53 #include "bktr.h"
54 #endif /* __FreeBSD__ */
55
56 #include "opt_bktr.h"           /* include any kernel config options */
57
58 #define FIFO_RISC_DISABLED      0
59 #define ALL_INTS_DISABLED       0
60
61
62 /*******************/
63 /* *** FreeBSD *** */
64 /*******************/
65 #ifdef __FreeBSD__
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/conf.h>
70 #include <sys/uio.h>
71 #include <sys/kernel.h>
72 #include <sys/signalvar.h>
73 #include <sys/mman.h>
74 #include <sys/poll.h>
75 #include <sys/select.h>
76 #include <sys/vnode.h>
77
78 #include <vm/vm.h>
79 #include <vm/vm_kern.h>
80 #include <vm/pmap.h>
81 #include <vm/vm_extern.h>
82
83 #if (__FreeBSD_version >=400000) || (NSMBUS > 0)
84 #include <sys/bus.h>            /* used by smbus and newbus */
85 #endif
86
87 #if (__FreeBSD_version >=300000)
88 #include <machine/bus_memio.h>  /* used by bus space */
89 #include <machine/bus.h>        /* used by bus space and newbus */
90 #include <sys/bus.h>
91 #endif
92
93 #if (__FreeBSD_version >=400000)
94 #include <sys/rman.h>           /* used by newbus */
95 #include <machine/resource.h>   /* used by newbus */
96 #endif
97
98 #if (__FreeBSD_version < 500000)
99 #include <machine/clock.h>              /* for DELAY */
100 #endif
101
102 #include <pci/pcivar.h>
103 #include <pci/pcireg.h>
104
105 #include <sys/sysctl.h>
106 int bt848_card = -1; 
107 int bt848_tuner = -1;
108 int bt848_reverse_mute = -1; 
109 int bt848_format = -1;
110 int bt848_slow_msp_audio = -1;
111
112 SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
113 SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
114 SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
115 SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
116 SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
117 SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
118
119 #if (__FreeBSD__ == 2)
120 #define PCIR_REVID     PCI_CLASS_REG
121 #endif
122
123 #endif /* end freebsd section */
124
125
126
127 /****************/
128 /* *** BSDI *** */
129 /****************/
130 #ifdef __bsdi__
131 #endif /* __bsdi__ */
132
133
134 /**************************/
135 /* *** OpenBSD/NetBSD *** */
136 /**************************/
137 #if defined(__NetBSD__) || defined(__OpenBSD__)
138
139 #include <sys/param.h>
140 #include <sys/systm.h>
141 #include <sys/conf.h>
142 #include <sys/uio.h>
143 #include <sys/kernel.h>
144 #include <sys/signalvar.h>
145 #include <sys/mman.h>
146 #include <sys/poll.h>
147 #include <sys/select.h>
148 #include <sys/vnode.h>
149
150 #include <vm/vm.h>
151
152 #ifndef __NetBSD__
153 #include <vm/vm_kern.h>
154 #include <vm/pmap.h>
155 #include <vm/vm_extern.h>
156 #endif
157
158 #include <sys/device.h>
159 #include <dev/pci/pcivar.h>
160 #include <dev/pci/pcireg.h>
161 #include <dev/pci/pcidevs.h>
162
163 #define BKTR_DEBUG
164 #ifdef BKTR_DEBUG
165 int bktr_debug = 0;
166 #define DPR(x)  (bktr_debug ? printf x : 0)
167 #else
168 #define DPR(x)
169 #endif
170 #endif /* __NetBSD__ || __OpenBSD__ */
171
172
173 #ifdef __NetBSD__
174 #include <dev/ic/bt8xx.h>       /* NetBSD location for .h files */
175 #include <dev/pci/bktr/bktr_reg.h>
176 #include <dev/pci/bktr/bktr_tuner.h>
177 #include <dev/pci/bktr/bktr_card.h>
178 #include <dev/pci/bktr/bktr_audio.h>
179 #include <dev/pci/bktr/bktr_core.h>
180 #include <dev/pci/bktr/bktr_os.h>
181 #else                                   /* Traditional location for .h files */
182 #include <machine/ioctl_meteor.h>
183 #include <machine/ioctl_bt848.h>        /* extensions to ioctl_meteor.h */
184 #include <dev/bktr/bktr_reg.h>
185 #include <dev/bktr/bktr_tuner.h>
186 #include <dev/bktr/bktr_card.h>
187 #include <dev/bktr/bktr_audio.h>
188 #include <dev/bktr/bktr_core.h>
189 #include <dev/bktr/bktr_os.h>
190 #if defined(BKTR_USE_FREEBSD_SMBUS)
191 #include <dev/bktr/bktr_i2c.h>
192 #endif
193 #endif
194
195
196
197 /****************************/
198 /* *** FreeBSD 4.x code *** */
199 /****************************/
200 #if (__FreeBSD_version >= 400000)
201
202 static int      bktr_probe( device_t dev );
203 static int      bktr_attach( device_t dev );
204 static int      bktr_detach( device_t dev );
205 static int      bktr_shutdown( device_t dev );
206 static void     bktr_intr(void *arg) { common_bktr_intr(arg); }
207
208 static device_method_t bktr_methods[] = {
209         /* Device interface */
210         DEVMETHOD(device_probe,         bktr_probe),
211         DEVMETHOD(device_attach,        bktr_attach),
212         DEVMETHOD(device_detach,        bktr_detach),
213         DEVMETHOD(device_shutdown,      bktr_shutdown),
214
215         { 0, 0 }
216 };
217
218 static driver_t bktr_driver = {
219         "bktr",
220         bktr_methods,
221         sizeof(struct bktr_softc),
222 };
223
224 static devclass_t bktr_devclass;
225
226 static  d_open_t        bktr_open;
227 static  d_close_t       bktr_close;
228 static  d_read_t        bktr_read;
229 static  d_write_t       bktr_write;
230 static  d_ioctl_t       bktr_ioctl;
231 static  d_mmap_t        bktr_mmap;
232 static  d_poll_t        bktr_poll;
233
234 #define CDEV_MAJOR 92 
235 static struct cdevsw bktr_cdevsw = {
236         /* open */      bktr_open,
237         /* close */     bktr_close,
238         /* read */      bktr_read,
239         /* write */     bktr_write,
240         /* ioctl */     bktr_ioctl,
241         /* poll */      bktr_poll,
242         /* mmap */      bktr_mmap,
243         /* strategy */  nostrategy,
244         /* name */      "bktr",
245         /* maj */       CDEV_MAJOR,
246         /* dump */      nodump,
247         /* psize */     nopsize,
248         /* flags */     0,
249         /* bmaj */      -1
250 };
251
252 DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0);
253 #if (__FreeBSD_version > 410000)
254 MODULE_DEPEND(bktr, bktr_mem, 1,1,1);
255 MODULE_VERSION(bktr, 1);
256 #endif
257
258
259 /*
260  * the boot time probe routine.
261  */
262 static int
263 bktr_probe( device_t dev )
264 {
265         unsigned int type = pci_get_devid(dev);
266         unsigned int rev  = pci_get_revid(dev);
267
268         if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
269         {
270                 switch (PCI_PRODUCT(type)) {
271                 case PCI_PRODUCT_BROOKTREE_BT848:
272                         if (rev == 0x12)
273                                 device_set_desc(dev, "BrookTree 848A");
274                         else
275                                 device_set_desc(dev, "BrookTree 848");
276                         return 0;
277                 case PCI_PRODUCT_BROOKTREE_BT849:
278                         device_set_desc(dev, "BrookTree 849A");
279                         return 0;
280                 case PCI_PRODUCT_BROOKTREE_BT878:
281                         device_set_desc(dev, "BrookTree 878");
282                         return 0;
283                 case PCI_PRODUCT_BROOKTREE_BT879:
284                         device_set_desc(dev, "BrookTree 879");
285                         return 0;
286                 }
287         };
288
289         return ENXIO;
290 }
291
292
293 /*
294  * the attach routine.
295  */
296 static int
297 bktr_attach( device_t dev )
298 {
299         u_long          latency;
300         u_long          fun;
301         u_long          val;
302         unsigned int    rev;
303         unsigned int    unit;
304         int             error = 0;
305 #ifdef BROOKTREE_IRQ
306         u_long          old_irq, new_irq;
307 #endif 
308
309         struct bktr_softc *bktr = device_get_softc(dev);
310
311         unit = device_get_unit(dev);
312
313         /* build the device name for bktr_name() */
314         snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
315
316         /*
317          * Enable bus mastering and Memory Mapped device
318          */
319         val = pci_read_config(dev, PCIR_COMMAND, 4);
320         val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
321         pci_write_config(dev, PCIR_COMMAND, val, 4);
322
323         /*
324          * Map control/status registers.
325          */
326         bktr->mem_rid = PCIR_MAPS;
327         bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid,
328                                         0, ~0, 1, RF_ACTIVE);
329
330
331         if (!bktr->res_mem) {
332                 device_printf(dev, "could not map memory\n");
333                 error = ENXIO;
334                 goto fail;
335         }
336         bktr->memt = rman_get_bustag(bktr->res_mem);
337         bktr->memh = rman_get_bushandle(bktr->res_mem);
338
339
340         /*
341          * Disable the brooktree device
342          */
343         OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
344         OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
345
346
347 #ifdef BROOKTREE_IRQ            /* from the configuration file */
348         old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
349         pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
350         new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
351         printf("bktr%d: attach: irq changed from %d to %d\n",
352                 unit, (old_irq & 0xff), (new_irq & 0xff));
353 #endif 
354
355         /*
356          * Allocate our interrupt.
357          */
358         bktr->irq_rid = 0;
359         bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid,
360                                 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
361         if (bktr->res_irq == NULL) {
362                 device_printf(dev, "could not map interrupt\n");
363                 error = ENXIO;
364                 goto fail;
365         }
366
367         error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY,
368                                bktr_intr, bktr, &bktr->res_ih);
369         if (error) {
370                 device_printf(dev, "could not setup irq\n");
371                 goto fail;
372
373         }
374
375
376         /* Update the Device Control Register */
377         /* on Bt878 and Bt879 cards           */
378         fun = pci_read_config( dev, 0x40, 2);
379         fun = fun | 1;  /* Enable writes to the sub-system vendor ID */
380
381 #if defined( BKTR_430_FX_MODE )
382         if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
383         fun = fun | 2;  /* Enable Intel 430 FX compatibility mode */
384 #endif
385
386 #if defined( BKTR_SIS_VIA_MODE )
387         if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
388         fun = fun | 4;  /* Enable SiS/VIA compatibility mode (usefull for
389                            OPTi chipset motherboards too */
390 #endif
391         pci_write_config(dev, 0x40, fun, 2);
392
393
394         /* XXX call bt848_i2c dependent attach() routine */
395 #if defined(BKTR_USE_FREEBSD_SMBUS)
396         if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc))
397                 printf("bktr%d: i2c_attach: can't attach\n", unit);
398 #endif
399
400
401 /*
402  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
403  * you have more than four, then 16 would probably be a better value.
404  */
405 #ifndef BROOKTREE_DEF_LATENCY_VALUE
406 #define BROOKTREE_DEF_LATENCY_VALUE     10
407 #endif
408         latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4);
409         latency = (latency >> 8) & 0xff;
410         if ( bootverbose ) {
411                 if (latency)
412                         printf("brooktree%d: PCI bus latency is", unit);
413                 else
414                         printf("brooktree%d: PCI bus latency was 0 changing to",
415                                 unit);
416         }
417         if ( !latency ) {
418                 latency = BROOKTREE_DEF_LATENCY_VALUE;
419                 pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4);
420         }
421         if ( bootverbose ) {
422                 printf(" %d.\n", (int) latency);
423         }
424
425         /* read the pci device id and revision id */
426         fun = pci_get_devid(dev);
427         rev = pci_get_revid(dev);
428
429         /* call the common attach code */
430         common_bktr_attach( bktr, unit, fun, rev );
431
432         /* make the device entries */
433         bktr->bktrdev = make_dev(&bktr_cdevsw, unit,    
434                                 0, 0, 0444, "bktr%d",  unit);
435         bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16,
436                                 0, 0, 0444, "tuner%d", unit);
437         bktr->vbidev  = make_dev(&bktr_cdevsw, unit+32,
438                                 0, 0, 0444, "vbi%d"  , unit);
439
440
441         /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */
442         /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */
443 #if (__FreeBSD_version >=500000)
444         if (unit == 0) {
445                 bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev,  "bktr");
446                 bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner");
447                 bktr->vbidev_alias  = make_dev_alias(bktr->vbidev,   "vbi");
448         }
449 #endif
450
451         return 0;
452
453 fail:
454         if (bktr->res_irq)
455                 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
456         if (bktr->res_mem)
457                 bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem);
458         return error;
459
460 }
461
462 /*
463  * the detach routine.
464  */
465 static int
466 bktr_detach( device_t dev )
467 {
468         unsigned int    unit;
469
470         struct bktr_softc *bktr = device_get_softc(dev);
471
472         unit = device_get_unit(dev);
473
474         /* Disable the brooktree device */
475         OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
476         OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
477
478         /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */
479         /* The memory is retained by the bktr_mem module so we can unload and */
480         /* then reload the main bktr driver module */
481
482         /* Unregister the /dev/bktrN, tunerN and vbiN devices */
483         destroy_dev(bktr->vbidev);
484         destroy_dev(bktr->tunerdev);
485         destroy_dev(bktr->bktrdev);
486
487         /* If this is unit 0, then destroy the alias entries too */
488 #if (__FreeBSD_version >=500000)
489         if (unit == 0) {
490             destroy_dev(bktr->vbidev_alias);
491             destroy_dev(bktr->tunerdev_alias);
492             destroy_dev(bktr->bktrdev_alias);
493         }
494 #endif
495
496         /*
497          * Deallocate resources.
498          */
499         bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
500         bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
501         bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
502          
503         return 0;
504 }
505
506 /*
507  * the shutdown routine.
508  */
509 static int
510 bktr_shutdown( device_t dev )
511 {
512         struct bktr_softc *bktr = device_get_softc(dev);
513
514         /* Disable the brooktree device */
515         OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
516         OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
517
518         return 0;
519 }
520
521
522 /*
523  * Special Memory Allocation
524  */
525 vm_offset_t
526 get_bktr_mem( int unit, unsigned size )
527 {
528         vm_offset_t     addr = 0;
529
530         addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
531         if (addr == 0)
532                 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
533         if (addr == 0) {
534                 printf("bktr%d: Unable to allocate %d bytes of memory.\n",
535                         unit, size);
536         }
537
538         return( addr );
539 }
540
541
542 /*---------------------------------------------------------
543 **
544 **      BrookTree 848 character device driver routines
545 **
546 **---------------------------------------------------------
547 */
548
549 #define VIDEO_DEV       0x00
550 #define TUNER_DEV       0x01
551 #define VBI_DEV         0x02
552
553 #define UNIT(x)         ((x) & 0x0f)
554 #define FUNCTION(x)     (x >> 4)
555
556 /*
557  * 
558  */
559 int
560 bktr_open( dev_t dev, int flags, int fmt, d_thread_t *td)
561 {
562         bktr_ptr_t      bktr;
563         int             unit;
564         int             result;
565
566         unit = UNIT( minor(dev) );
567
568         /* Get the device data */
569         bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
570         if (bktr == NULL) {
571                 /* the device is no longer valid/functioning */
572                 return (ENXIO);
573         }
574
575         if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
576                 return( ENXIO );        
577
578         /* Record that the device is now busy */
579         device_busy(devclass_get_device(bktr_devclass, unit)); 
580
581
582         if (bt848_card != -1) {
583           if ((bt848_card >> 8   == unit ) &&
584              ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
585             if ( bktr->bt848_card != (bt848_card & 0xff) ) {
586               bktr->bt848_card = (bt848_card & 0xff);
587               probeCard(bktr, FALSE, unit);
588             }
589           }
590         }
591
592         if (bt848_tuner != -1) {
593           if ((bt848_tuner >> 8   == unit ) &&
594              ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
595             if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
596               bktr->bt848_tuner = (bt848_tuner & 0xff);
597               probeCard(bktr, FALSE, unit);
598             }
599           }
600         }
601
602         if (bt848_reverse_mute != -1) {
603           if ((bt848_reverse_mute >> 8)   == unit ) {
604             bktr->reverse_mute = bt848_reverse_mute & 0xff;
605           }
606         }
607
608         if (bt848_slow_msp_audio != -1) {
609           if ((bt848_slow_msp_audio >> 8) == unit ) {
610               bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
611           }
612         }
613
614         switch ( FUNCTION( minor(dev) ) ) {
615         case VIDEO_DEV:
616                 result = video_open( bktr );
617                 break;
618         case TUNER_DEV:
619                 result = tuner_open( bktr );
620                 break;
621         case VBI_DEV:
622                 result = vbi_open( bktr );
623                 break;
624         default:
625                 result = ENXIO;
626                 break;
627         }
628
629         /* If there was an error opening the device, undo the busy status */
630         if (result != 0)
631                 device_unbusy(devclass_get_device(bktr_devclass, unit)); 
632         return( result );
633 }
634
635
636 /*
637  * 
638  */
639 int
640 bktr_close( dev_t dev, int flags, int fmt, d_thread_t *td)
641 {
642         bktr_ptr_t      bktr;
643         int             unit;
644         int             result;
645
646         unit = UNIT( minor(dev) );
647
648         /* Get the device data */
649         bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
650         if (bktr == NULL) {
651                 /* the device is no longer valid/functioning */
652                 return (ENXIO);
653         }
654
655         switch ( FUNCTION( minor(dev) ) ) {
656         case VIDEO_DEV:
657                 result = video_close( bktr );
658                 break;
659         case TUNER_DEV:
660                 result = tuner_close( bktr );
661                 break;
662         case VBI_DEV:
663                 result = vbi_close( bktr );
664                 break;
665         default:
666                 return (ENXIO);
667                 break;
668         }
669
670         device_unbusy(devclass_get_device(bktr_devclass, unit)); 
671         return( result );
672 }
673
674
675 /*
676  * 
677  */
678 int
679 bktr_read( dev_t dev, struct uio *uio, int ioflag )
680 {
681         bktr_ptr_t      bktr;
682         int             unit;
683         
684         unit = UNIT(minor(dev));
685
686         /* Get the device data */
687         bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
688         if (bktr == NULL) {
689                 /* the device is no longer valid/functioning */
690                 return (ENXIO);
691         }
692
693         switch ( FUNCTION( minor(dev) ) ) {
694         case VIDEO_DEV:
695                 return( video_read( bktr, unit, dev, uio ) );
696         case VBI_DEV:
697                 return( vbi_read( bktr, uio, ioflag ) );
698         }
699         return( ENXIO );
700 }
701
702
703 /*
704  * 
705  */
706 int
707 bktr_write( dev_t dev, struct uio *uio, int ioflag )
708 {
709         return( EINVAL ); /* XXX or ENXIO ? */
710 }
711
712
713 /*
714  * 
715  */
716 int
717 bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, d_thread_t *td)
718 {
719         bktr_ptr_t      bktr;
720         int             unit;
721
722         unit = UNIT(minor(dev));
723
724         /* Get the device data */
725         bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
726         if (bktr == NULL) {
727                 /* the device is no longer valid/functioning */
728                 return (ENXIO);
729         }
730
731         if (bktr->bigbuf == 0)  /* no frame buffer allocated (ioctl failed) */
732                 return( ENOMEM );
733
734         switch ( FUNCTION( minor(dev) ) ) {
735         case VIDEO_DEV:
736                 return( video_ioctl( bktr, unit, cmd, arg, td ) );
737         case TUNER_DEV:
738                 return( tuner_ioctl( bktr, unit, cmd, arg, td ) );
739         }
740
741         return( ENXIO );
742 }
743
744
745 /*
746  * 
747  */
748 int
749 bktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
750 {
751         int             unit;
752         bktr_ptr_t      bktr;
753
754         unit = UNIT(minor(dev));
755
756         if (FUNCTION(minor(dev)) > 0)   /* only allow mmap on /dev/bktr[n] */
757                 return( -1 );
758
759         /* Get the device data */
760         bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
761         if (bktr == NULL) {
762                 /* the device is no longer valid/functioning */
763                 return (ENXIO);
764         }
765
766         if (nprot & PROT_EXEC)
767                 return( -1 );
768
769         if (offset < 0)
770                 return( -1 );
771
772         if (offset >= bktr->alloc_pages * PAGE_SIZE)
773                 return( -1 );
774
775         return( atop(vtophys(bktr->bigbuf) + offset) );
776 }
777
778 int bktr_poll( dev_t dev, int events, d_thread_t *td)
779 {
780         int             unit;
781         bktr_ptr_t      bktr;
782         int revents = 0; 
783         DECLARE_INTR_MASK(s);
784
785         unit = UNIT(minor(dev));
786
787         /* Get the device data */
788         bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
789         if (bktr == NULL) {
790                 /* the device is no longer valid/functioning */
791                 return (ENXIO);
792         }
793
794         DISABLE_INTR(s);
795
796         if (events & (POLLIN | POLLRDNORM)) {
797
798                 switch ( FUNCTION( minor(dev) ) ) {
799                 case VBI_DEV:
800                         if(bktr->vbisize == 0)
801                                 selrecord(td, &bktr->vbi_select);
802                         else
803                                 revents |= events & (POLLIN | POLLRDNORM);
804                         break;
805                 }
806         }
807
808         ENABLE_INTR(s);
809
810         return (revents);
811 }
812
813 #endif          /* FreeBSD 4.x specific kernel interface routines */
814
815 /**********************************/
816 /* *** FreeBSD 2.2.x and 3.x  *** */
817 /**********************************/
818
819 #if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3))
820
821 static bktr_reg_t brooktree[ NBKTR ];
822
823 static const char*      bktr_probe( pcici_t tag, pcidi_t type );
824 static void             bktr_attach( pcici_t tag, int unit );
825 static void             bktr_intr(void *arg) { common_bktr_intr(arg); }
826
827 static u_long   bktr_count;
828
829 static struct   pci_device bktr_device = {
830         "bktr",
831         bktr_probe,
832         bktr_attach,
833         &bktr_count
834 };
835
836 DATA_SET (pcidevice_set, bktr_device);
837
838 static  d_open_t        bktr_open;
839 static  d_close_t       bktr_close;
840 static  d_read_t        bktr_read;
841 static  d_write_t       bktr_write;
842 static  d_ioctl_t       bktr_ioctl;
843 static  d_mmap_t        bktr_mmap;
844 static  d_poll_t        bktr_poll;
845
846 #define CDEV_MAJOR 92 
847 static struct cdevsw bktr_cdevsw = 
848 {
849         bktr_open,      bktr_close,     bktr_read,      bktr_write,
850         bktr_ioctl,     nostop,         nullreset,      nodevtotty,
851         bktr_poll,      bktr_mmap,      NULL,           "bktr",
852         NULL,           -1
853 };
854
855 static int bktr_devsw_installed;
856
857 static void
858 bktr_drvinit( void *unused )
859 {
860         dev_t dev;
861
862         if ( ! bktr_devsw_installed ) {
863                 dev = makedev(CDEV_MAJOR, 0);
864                 cdevsw_add(&dev,&bktr_cdevsw, NULL);
865                 bktr_devsw_installed = 1;
866         }
867 }
868
869 SYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL)
870
871 /*
872  * the boot time probe routine.
873  */
874 static const char*
875 bktr_probe( pcici_t tag, pcidi_t type )
876 {
877         unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff;
878
879         if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
880         {
881                 switch (PCI_PRODUCT(type)) {
882                 case PCI_PRODUCT_BROOKTREE_BT848:
883                         if (rev == 0x12) return("BrookTree 848A");
884                         else             return("BrookTree 848");
885                 case PCI_PRODUCT_BROOKTREE_BT849:
886                         return("BrookTree 849A");
887                 case PCI_PRODUCT_BROOKTREE_BT878:
888                         return("BrookTree 878");
889                 case PCI_PRODUCT_BROOKTREE_BT879:
890                         return("BrookTree 879");
891                 }
892         };
893
894         return ((char *)0);
895 }
896
897 /*
898  * the attach routine.
899  */
900 static  void
901 bktr_attach( pcici_t tag, int unit )
902 {
903         bktr_ptr_t      bktr;
904         u_long          latency;
905         u_long          fun;
906         unsigned int    rev;
907         unsigned long   base;
908 #ifdef BROOKTREE_IRQ
909         u_long          old_irq, new_irq;
910 #endif 
911
912         bktr = &brooktree[unit];
913
914         if (unit >= NBKTR) {
915                 printf("brooktree%d: attach: only %d units configured.\n",
916                         unit, NBKTR);
917                 printf("brooktree%d: attach: invalid unit number.\n", unit);
918                 return;
919         }
920
921         /* build the device name for bktr_name() */
922         snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
923
924         /* Enable Memory Mapping */
925         fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
926         pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2);
927
928         /* Enable Bus Mastering */
929         fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG);
930         pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4);
931
932         bktr->tag = tag;
933
934
935         /*
936          * Map control/status registers
937          */
938         pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base,
939                      &bktr->phys_base );
940 #if (__FreeBSD_version >= 300000)
941         bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */
942         bktr->memh = (bus_space_handle_t)base; /* XXX functions here */
943 #endif
944
945         /*
946          * Disable the brooktree device
947          */
948         OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
949         OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
950
951 #ifdef BROOKTREE_IRQ            /* from the configuration file */
952         old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
953         pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
954         new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
955         printf("bktr%d: attach: irq changed from %d to %d\n",
956                 unit, (old_irq & 0xff), (new_irq & 0xff));
957 #endif 
958
959         /*
960          * setup the interrupt handling routine
961          */
962         pci_map_int(tag, bktr_intr, (void*) bktr, &tty_imask);
963
964
965         /* Update the Device Control Register */
966         /* on Bt878 and Bt879 cards */
967         fun = pci_conf_read(tag, 0x40);
968         fun = fun | 1;  /* Enable writes to the sub-system vendor ID */
969
970 #if defined( BKTR_430_FX_MODE )
971         if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
972         fun = fun | 2;  /* Enable Intel 430 FX compatibility mode */
973 #endif
974
975 #if defined( BKTR_SIS_VIA_MODE )
976         if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
977         fun = fun | 4;  /* Enable SiS/VIA compatibility mode (usefull for
978                            OPTi chipset motherboards too */
979 #endif
980         pci_conf_write(tag, 0x40, fun);
981
982
983         /* XXX call bt848_i2c dependent attach() routine */
984 #if defined(BKTR_USE_FREEBSD_SMBUS)
985         if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc))
986                 printf("bktr%d: i2c_attach: can't attach\n", unit);
987 #endif
988
989
990 /*
991  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
992  * you have more than four, then 16 would probably be a better value.
993  */
994 #ifndef BROOKTREE_DEF_LATENCY_VALUE
995 #define BROOKTREE_DEF_LATENCY_VALUE     10
996 #endif
997         latency = pci_conf_read(tag, PCI_LATENCY_TIMER);
998         latency = (latency >> 8) & 0xff;
999         if ( bootverbose ) {
1000                 if (latency)
1001                         printf("brooktree%d: PCI bus latency is", unit);
1002                 else
1003                         printf("brooktree%d: PCI bus latency was 0 changing to",
1004                                 unit);
1005         }
1006         if ( !latency ) {
1007                 latency = BROOKTREE_DEF_LATENCY_VALUE;
1008                 pci_conf_write(tag, PCI_LATENCY_TIMER,  latency<<8);
1009         }
1010         if ( bootverbose ) {
1011                 printf(" %d.\n", (int) latency);
1012         }
1013
1014
1015         /* read the pci device id and revision id */
1016         fun = pci_conf_read(tag, PCI_ID_REG);
1017         rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff;
1018
1019         /* call the common attach code */
1020         common_bktr_attach( bktr, unit, fun, rev );
1021
1022 }
1023
1024
1025 /*
1026  * Special Memory Allocation
1027  */
1028 vm_offset_t
1029 get_bktr_mem( int unit, unsigned size )
1030 {
1031         vm_offset_t     addr = 0;
1032
1033         addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24);
1034         if (addr == 0)
1035                 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff,
1036                                                                 PAGE_SIZE);
1037         if (addr == 0) {
1038                 printf("bktr%d: Unable to allocate %d bytes of memory.\n",
1039                         unit, size);
1040         }
1041
1042         return( addr );
1043 }
1044
1045 /*---------------------------------------------------------
1046 **
1047 **      BrookTree 848 character device driver routines
1048 **
1049 **---------------------------------------------------------
1050 */
1051
1052
1053 #define VIDEO_DEV       0x00
1054 #define TUNER_DEV       0x01
1055 #define VBI_DEV         0x02
1056
1057 #define UNIT(x)         ((x) & 0x0f)
1058 #define FUNCTION(x)     ((x >> 4) & 0x0f)
1059
1060
1061 /*
1062  * 
1063  */
1064 int
1065 bktr_open( dev_t dev, int flags, int fmt, d_thread_t *td)
1066 {
1067         bktr_ptr_t      bktr;
1068         int             unit;
1069
1070         unit = UNIT( minor(dev) );
1071         if (unit >= NBKTR)                      /* unit out of range */
1072                 return( ENXIO );
1073
1074         bktr = &(brooktree[ unit ]);
1075
1076         if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1077                 return( ENXIO );        
1078
1079
1080         if (bt848_card != -1) {
1081           if ((bt848_card >> 8   == unit ) &&
1082              ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
1083             if ( bktr->bt848_card != (bt848_card & 0xff) ) {
1084               bktr->bt848_card = (bt848_card & 0xff);
1085               probeCard(bktr, FALSE, unit);
1086             }
1087           }
1088         }
1089
1090         if (bt848_tuner != -1) {
1091           if ((bt848_tuner >> 8   == unit ) &&
1092              ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
1093             if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
1094               bktr->bt848_tuner = (bt848_tuner & 0xff);
1095               probeCard(bktr, FALSE, unit);
1096             }
1097           }
1098         }
1099
1100         if (bt848_reverse_mute != -1) {
1101           if ((bt848_reverse_mute >> 8)   == unit ) {
1102             bktr->reverse_mute = bt848_reverse_mute & 0xff;
1103           }
1104         }
1105
1106         if (bt848_slow_msp_audio != -1) {
1107           if ((bt848_slow_msp_audio >> 8) == unit ) {
1108               bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
1109           }
1110         }
1111
1112         switch ( FUNCTION( minor(dev) ) ) {
1113         case VIDEO_DEV:
1114                 return( video_open( bktr ) );
1115         case TUNER_DEV:
1116                 return( tuner_open( bktr ) );
1117         case VBI_DEV:
1118                 return( vbi_open( bktr ) );
1119         }
1120         return( ENXIO );
1121 }
1122
1123
1124 /*
1125  * 
1126  */
1127 int
1128 bktr_close( dev_t dev, int flags, int fmt, d_thread_t *td)
1129 {
1130         bktr_ptr_t      bktr;
1131         int             unit;
1132
1133         unit = UNIT( minor(dev) );
1134         if (unit >= NBKTR)                      /* unit out of range */
1135                 return( ENXIO );
1136
1137         bktr = &(brooktree[ unit ]);
1138
1139         switch ( FUNCTION( minor(dev) ) ) {
1140         case VIDEO_DEV:
1141                 return( video_close( bktr ) );
1142         case TUNER_DEV:
1143                 return( tuner_close( bktr ) );
1144         case VBI_DEV:
1145                 return( vbi_close( bktr ) );
1146         }
1147
1148         return( ENXIO );
1149 }
1150
1151 /*
1152  * 
1153  */
1154 int
1155 bktr_read( dev_t dev, struct uio *uio, int ioflag )
1156 {
1157         bktr_ptr_t      bktr;
1158         int             unit;
1159         
1160         unit = UNIT(minor(dev));
1161         if (unit >= NBKTR)      /* unit out of range */
1162                 return( ENXIO );
1163
1164         bktr = &(brooktree[unit]);
1165
1166         switch ( FUNCTION( minor(dev) ) ) {
1167         case VIDEO_DEV:
1168                 return( video_read( bktr, unit, dev, uio ) );
1169         case VBI_DEV:
1170                 return( vbi_read( bktr, uio, ioflag ) );
1171         }
1172         return( ENXIO );
1173 }
1174
1175
1176 /*
1177  * 
1178  */
1179 int
1180 bktr_write( dev_t dev, struct uio *uio, int ioflag )
1181 {
1182         return( EINVAL ); /* XXX or ENXIO ? */
1183 }
1184
1185 /*
1186  * 
1187  */
1188 int
1189 bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, d_thread_t *td)
1190 {
1191         bktr_ptr_t      bktr;
1192         int             unit;
1193
1194         unit = UNIT(minor(dev));
1195         if (unit >= NBKTR)      /* unit out of range */
1196                 return( ENXIO );
1197
1198         bktr = &(brooktree[ unit ]);
1199
1200         if (bktr->bigbuf == 0)  /* no frame buffer allocated (ioctl failed) */
1201                 return( ENOMEM );
1202
1203         switch ( FUNCTION( minor(dev) ) ) {
1204         case VIDEO_DEV:
1205                 return( video_ioctl( bktr, unit, cmd, arg, td ) );
1206         case TUNER_DEV:
1207                 return( tuner_ioctl( bktr, unit, cmd, arg, td ) );
1208         }
1209
1210         return( ENXIO );
1211 }
1212
1213 /*
1214  * bktr_mmap.
1215  * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually
1216  * edit the line below and change  "vm_offset_t" to "int"
1217  */
1218 int bktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
1219
1220 {
1221         int             unit;
1222         bktr_ptr_t      bktr;
1223
1224         unit = UNIT(minor(dev));
1225
1226         if (unit >= NBKTR || FUNCTION(minor(dev)) > 0)
1227                 return( -1 );
1228
1229         bktr = &(brooktree[ unit ]);
1230
1231         if (nprot & PROT_EXEC)
1232                 return( -1 );
1233
1234         if (offset < 0)
1235                 return( -1 );
1236
1237         if (offset >= bktr->alloc_pages * PAGE_SIZE)
1238                 return( -1 );
1239
1240         return( i386_btop(vtophys(bktr->bigbuf) + offset) );
1241 }
1242
1243 int bktr_poll( dev_t dev, int events, d_thread_t *td)
1244 {
1245         int             unit;
1246         bktr_ptr_t      bktr;
1247         int revents = 0; 
1248
1249         unit = UNIT(minor(dev));
1250
1251         if (unit >= NBKTR)
1252                 return( -1 );
1253
1254         bktr = &(brooktree[ unit ]);
1255
1256         disable_intr();
1257
1258         if (events & (POLLIN | POLLRDNORM)) {
1259
1260                 switch ( FUNCTION( minor(dev) ) ) {
1261                 case VBI_DEV:
1262                         if(bktr->vbisize == 0)
1263                                 selrecord(p, &bktr->vbi_select);
1264                         else
1265                                 revents |= events & (POLLIN | POLLRDNORM);
1266                         break;
1267                 }
1268         }
1269
1270         enable_intr();
1271
1272         return (revents);
1273 }
1274
1275
1276 #endif          /* FreeBSD 2.2.x and 3.x specific kernel interface routines */
1277
1278
1279 /*****************/
1280 /* *** BSDI  *** */
1281 /*****************/
1282
1283 #if defined(__bsdi__)
1284 #endif          /* __bsdi__ BSDI specific kernel interface routines */
1285
1286
1287 /*****************************/
1288 /* *** OpenBSD / NetBSD  *** */
1289 /*****************************/
1290 #if defined(__NetBSD__) || defined(__OpenBSD__)
1291
1292 #define IPL_VIDEO       IPL_BIO         /* XXX */
1293
1294 static  int             bktr_intr(void *arg) { return common_bktr_intr(arg); }
1295
1296 #define bktr_open       bktropen
1297 #define bktr_close      bktrclose
1298 #define bktr_read       bktrread
1299 #define bktr_write      bktrwrite
1300 #define bktr_ioctl      bktrioctl
1301 #define bktr_mmap       bktrmmap
1302
1303 vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
1304                                  vm_offset_t, vm_offset_t);
1305
1306 #if defined(__OpenBSD__)
1307 static int      bktr_probe __P((struct device *, void *, void *));
1308 #else
1309 static int      bktr_probe __P((struct device *, struct cfdata *, void *));
1310 #endif
1311 static void     bktr_attach __P((struct device *, struct device *, void *));
1312
1313 struct cfattach bktr_ca = {
1314         sizeof(struct bktr_softc), bktr_probe, bktr_attach
1315 };
1316
1317 #if defined(__NetBSD__)
1318 extern struct cfdriver bktr_cd;
1319 #else
1320 struct cfdriver bktr_cd = {
1321         NULL, "bktr", DV_DULL
1322 };
1323 #endif
1324
1325 int
1326 bktr_probe(parent, match, aux)
1327         struct device *parent;
1328 #if defined(__OpenBSD__)
1329         void *match;
1330 #else
1331         struct cfdata *match;
1332 #endif
1333         void *aux;
1334 {
1335         struct pci_attach_args *pa = aux;
1336
1337         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
1338             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
1339              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
1340              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
1341              PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
1342                 return 1;
1343
1344         return 0;
1345 }
1346
1347
1348 /*
1349  * the attach routine.
1350  */
1351 static void
1352 bktr_attach(struct device *parent, struct device *self, void *aux)
1353 {
1354         bktr_ptr_t      bktr;
1355         u_long          latency;
1356         u_long          fun;
1357         unsigned int    rev;
1358
1359 #if defined(__OpenBSD__)
1360         struct pci_attach_args *pa = aux;
1361         pci_chipset_tag_t pc = pa->pa_pc;
1362
1363         pci_intr_handle_t ih;
1364         const char *intrstr;
1365         int retval;
1366         int unit;
1367
1368         bktr = (bktr_ptr_t)self;
1369         unit = bktr->bktr_dev.dv_unit;
1370
1371         bktr->pc = pa->pa_pc;
1372         bktr->tag = pa->pa_tag;
1373         bktr->dmat = pa->pa_dmat;
1374
1375         /*
1376          * map memory
1377          */
1378         bktr->memt = pa->pa_memt;
1379         retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 
1380                               &bktr->phys_base, &bktr->obmemsz, NULL);
1381         if (!retval)
1382                 retval = bus_space_map(pa->pa_memt, bktr->phys_base,
1383                                        bktr->obmemsz, 0, &bktr->memh);
1384         if (retval) {
1385                 printf(": couldn't map memory\n");
1386                 return;
1387         }
1388
1389
1390         /*
1391          * map interrupt
1392          */
1393         if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
1394                          pa->pa_intrline, &ih)) {
1395                 printf(": couldn't map interrupt\n");
1396                 return;
1397         }
1398         intrstr = pci_intr_string(pa->pa_pc, ih);
1399
1400         bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
1401                                       bktr_intr, bktr, bktr->bktr_dev.dv_xname);
1402         if (bktr->ih == NULL) {
1403                 printf(": couldn't establish interrupt");
1404                 if (intrstr != NULL)    
1405                         printf(" at %s", intrstr);
1406                 printf("\n");
1407                 return;
1408         }
1409
1410         if (intrstr != NULL)
1411                 printf(": %s\n", intrstr);
1412 #endif /* __OpenBSD__ */
1413
1414 #if defined(__NetBSD__) 
1415         struct pci_attach_args *pa = aux;
1416         pci_intr_handle_t ih;
1417         const char *intrstr;
1418         int retval;
1419         int unit;
1420
1421         bktr = (bktr_ptr_t)self;
1422         unit = bktr->bktr_dev.dv_unit;
1423         bktr->dmat = pa->pa_dmat;
1424
1425         printf("\n");
1426
1427         /*
1428          * map memory
1429          */
1430         retval = pci_mapreg_map(pa, PCI_MAPREG_START,
1431                                 PCI_MAPREG_TYPE_MEM
1432                                 | PCI_MAPREG_MEM_TYPE_32BIT, 0,
1433                                 &bktr->memt, &bktr->memh, NULL,
1434                                 &bktr->obmemsz);
1435         DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n",
1436              bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz));
1437         if (retval) {
1438                 printf("%s: couldn't map memory\n", bktr_name(bktr));
1439                 return;
1440         }
1441
1442         /*
1443          * Disable the brooktree device
1444          */
1445         OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
1446         OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
1447         
1448         /*
1449          * map interrupt
1450          */
1451         if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
1452                          pa->pa_intrline, &ih)) {
1453                 printf("%s: couldn't map interrupt\n",
1454                        bktr_name(bktr));
1455                 return;
1456         }
1457         intrstr = pci_intr_string(pa->pa_pc, ih);
1458         bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
1459                                       bktr_intr, bktr);
1460         if (bktr->ih == NULL) {
1461                 printf("%s: couldn't establish interrupt",
1462                        bktr_name(bktr));
1463                 if (intrstr != NULL)
1464                         printf(" at %s", intrstr);
1465                 printf("\n");
1466                 return;
1467         }
1468         if (intrstr != NULL)
1469                 printf("%s: interrupting at %s\n", bktr_name(bktr),
1470                        intrstr);
1471 #endif /* __NetBSD__ */
1472         
1473 /*
1474  * PCI latency timer.  32 is a good value for 4 bus mastering slots, if
1475  * you have more than four, then 16 would probably be a better value.
1476  */
1477 #ifndef BROOKTREE_DEF_LATENCY_VALUE
1478 #define BROOKTREE_DEF_LATENCY_VALUE     10
1479 #endif
1480         latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
1481         latency = (latency >> 8) & 0xff;
1482
1483         if (!latency) {
1484                 if (bootverbose) {
1485                         printf("%s: PCI bus latency was 0 changing to %d",
1486                                bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
1487                 }
1488                 latency = BROOKTREE_DEF_LATENCY_VALUE;
1489                 pci_conf_write(pa->pa_pc, pa->pa_tag, 
1490                                PCI_LATENCY_TIMER, latency<<8);
1491         }
1492
1493
1494         /* Enabled Bus Master
1495            XXX: check if all old DMA is stopped first (e.g. after warm
1496            boot) */
1497         fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
1498         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
1499                        fun | PCI_COMMAND_MASTER_ENABLE);
1500
1501         /* read the pci id and determine the card type */
1502         fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
1503         rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff;
1504
1505         common_bktr_attach(bktr, unit, fun, rev);
1506 }
1507
1508
1509 /*
1510  * Special Memory Allocation
1511  */
1512 vm_offset_t
1513 get_bktr_mem(bktr, dmapp, size)
1514         bktr_ptr_t bktr;
1515         bus_dmamap_t *dmapp;
1516         unsigned int size;
1517 {
1518         bus_dma_tag_t dmat = bktr->dmat;
1519         bus_dma_segment_t seg;
1520         bus_size_t align;
1521         int rseg;
1522         caddr_t kva;
1523
1524         /*
1525          * Allocate a DMA area
1526          */
1527         align = 1 << 24;
1528         if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1529                              &rseg, BUS_DMA_NOWAIT)) {
1530                 align = PAGE_SIZE;
1531                 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1532                                      &rseg, BUS_DMA_NOWAIT)) {
1533                         printf("%s: Unable to dmamem_alloc of %d bytes\n",
1534                                bktr_name(bktr), size);
1535                         return 0;
1536                 }
1537         }
1538         if (bus_dmamem_map(dmat, &seg, rseg, size,
1539                            &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1540                 printf("%s: Unable to dmamem_map of %d bytes\n",
1541                         bktr_name(bktr), size);
1542                 bus_dmamem_free(dmat, &seg, rseg);
1543                 return 0;
1544         }
1545 #ifdef __OpenBSD__
1546         bktr->dm_mapsize = size;
1547 #endif
1548         /*
1549          * Create and locd the DMA map for the DMA area
1550          */
1551         if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
1552                 printf("%s: Unable to dmamap_create of %d bytes\n",
1553                         bktr_name(bktr), size);
1554                 bus_dmamem_unmap(dmat, kva, size);
1555                 bus_dmamem_free(dmat, &seg, rseg);
1556                 return 0;
1557         }
1558         if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
1559                 printf("%s: Unable to dmamap_load of %d bytes\n",
1560                         bktr_name(bktr), size);
1561                 bus_dmamem_unmap(dmat, kva, size);
1562                 bus_dmamem_free(dmat, &seg, rseg);
1563                 bus_dmamap_destroy(dmat, *dmapp);
1564                 return 0;
1565         }
1566         return (vm_offset_t)kva;
1567 }
1568
1569 void
1570 free_bktr_mem(bktr, dmap, kva)
1571         bktr_ptr_t bktr;
1572         bus_dmamap_t dmap;
1573         vm_offset_t kva;
1574 {
1575         bus_dma_tag_t dmat = bktr->dmat;
1576
1577 #ifdef __NetBSD__ 
1578         bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
1579 #else
1580         bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize);
1581 #endif
1582         bus_dmamem_free(dmat, dmap->dm_segs, 1);
1583         bus_dmamap_destroy(dmat, dmap);
1584 }
1585
1586
1587 /*---------------------------------------------------------
1588 **
1589 **      BrookTree 848 character device driver routines
1590 **
1591 **---------------------------------------------------------
1592 */
1593
1594
1595 #define VIDEO_DEV       0x00
1596 #define TUNER_DEV       0x01
1597 #define VBI_DEV         0x02
1598
1599 #define UNIT(x)         (minor((x) & 0x0f))
1600 #define FUNCTION(x)     (minor((x >> 4) & 0x0f))
1601
1602 /*
1603  * 
1604  */
1605 int
1606 bktr_open(dev_t dev, int flags, int fmt, d_thread_t *td)
1607 {
1608         bktr_ptr_t      bktr;
1609         int             unit;
1610
1611         unit = UNIT(dev);
1612
1613         /* unit out of range */
1614         if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
1615                 return(ENXIO);
1616
1617         bktr = bktr_cd.cd_devs[unit];
1618
1619         if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1620                 return(ENXIO);  
1621
1622         switch (FUNCTION(dev)) {
1623         case VIDEO_DEV:
1624                 return(video_open(bktr));
1625         case TUNER_DEV:
1626                 return(tuner_open(bktr));
1627         case VBI_DEV:
1628                 return(vbi_open(bktr));
1629         }
1630
1631         return(ENXIO);
1632 }
1633
1634
1635 /*
1636  * 
1637  */
1638 int
1639 bktr_close(dev_t dev, int flags, int fmt, d_thread_t *td)
1640 {
1641         bktr_ptr_t      bktr;
1642         int             unit;
1643
1644         unit = UNIT(dev);
1645
1646         bktr = bktr_cd.cd_devs[unit];
1647
1648         switch (FUNCTION(dev)) {
1649         case VIDEO_DEV:
1650                 return(video_close(bktr));
1651         case TUNER_DEV:
1652                 return(tuner_close(bktr));
1653         case VBI_DEV:
1654                 return(vbi_close(bktr));
1655         }
1656
1657         return(ENXIO);
1658 }
1659
1660 /*
1661  * 
1662  */
1663 int
1664 bktr_read(dev_t dev, struct uio *uio, int ioflag)
1665 {
1666         bktr_ptr_t      bktr;
1667         int             unit;
1668         
1669         unit = UNIT(dev);
1670
1671         bktr = bktr_cd.cd_devs[unit];
1672
1673         switch (FUNCTION(dev)) {
1674         case VIDEO_DEV:
1675                 return(video_read(bktr, unit, dev, uio));
1676         case VBI_DEV:
1677                 return(vbi_read(bktr, uio, ioflag));
1678         }
1679
1680         return(ENXIO);
1681 }
1682
1683
1684 /*
1685  * 
1686  */
1687 int
1688 bktr_write(dev_t dev, struct uio *uio, int ioflag)
1689 {
1690         /* operation not supported */
1691         return(EOPNOTSUPP);
1692 }
1693
1694 /*
1695  * 
1696  */
1697 int
1698 bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, d_thread_t *td)
1699 {
1700         bktr_ptr_t      bktr;
1701         int             unit;
1702
1703         unit = UNIT(dev);
1704
1705         bktr = bktr_cd.cd_devs[unit];
1706
1707         if (bktr->bigbuf == 0)  /* no frame buffer allocated (ioctl failed) */
1708                 return(ENOMEM);
1709
1710         switch (FUNCTION(dev)) {
1711         case VIDEO_DEV:
1712                 return(video_ioctl(bktr, unit, cmd, arg, td));
1713         case TUNER_DEV:
1714                 return(tuner_ioctl(bktr, unit, cmd, arg, td));
1715         }
1716
1717         return(ENXIO);
1718 }
1719
1720 /*
1721  * 
1722  */
1723 paddr_t
1724 bktr_mmap(dev_t dev, off_t offset, int nprot)
1725 {
1726         int             unit;
1727         bktr_ptr_t      bktr;
1728
1729         unit = UNIT(dev);
1730
1731         if (FUNCTION(dev) > 0)  /* only allow mmap on /dev/bktr[n] */
1732                 return(-1);
1733
1734         bktr = bktr_cd.cd_devs[unit];
1735
1736         if ((vaddr_t)offset < 0)
1737                 return(-1);
1738
1739         if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
1740                 return(-1);
1741
1742 #ifdef __NetBSD__
1743         return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
1744                                 (vaddr_t)offset, nprot, BUS_DMA_WAITOK));
1745 #else
1746         return(i386_btop(vtophys(bktr->bigbuf) + offset));
1747 #endif
1748 }
1749
1750 #endif /* __NetBSD__ || __OpenBSD__ */