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