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