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