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