FreeBSD/Linux Kernel Cross Reference
sys/dev/bktr/bktr_os.c
1 /* $FreeBSD: releng/5.1/sys/dev/bktr/bktr_os.c 112569 2003-03-25 00:07:06Z jake $ */
2
3 /*
4 * This is part of the Driver for Video Capture Cards (Frame grabbers)
5 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879
6 * chipset.
7 * Copyright Roger Hardiman and Amancio Hasty.
8 *
9 * bktr_os : This has all the Operating System dependant code,
10 * probe/attach and open/close/ioctl/read/mmap
11 * memory allocation
12 * PCI bus interfacing
13 *
14 *
15 */
16
17 /*
18 * 1. Redistributions of source code must retain the
19 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * This product includes software developed by Amancio Hasty and
33 * Roger Hardiman
34 * 4. The name of the author may not be used to endorse or promote products
35 * derived from this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
38 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
41 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
46 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 * POSSIBILITY OF SUCH DAMAGE.
48 */
49
50
51 #include "opt_bktr.h" /* include any kernel config options */
52
53 #define FIFO_RISC_DISABLED 0
54 #define ALL_INTS_DISABLED 0
55
56
57 /*******************/
58 /* *** FreeBSD *** */
59 /*******************/
60 #ifdef __FreeBSD__
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/conf.h>
65 #include <sys/uio.h>
66 #include <sys/kernel.h>
67 #include <sys/signalvar.h>
68 #include <sys/mman.h>
69 #include <sys/poll.h>
70 #if __FreeBSD_version >= 500014
71 #include <sys/selinfo.h>
72 #else
73 #include <sys/select.h>
74 #endif
75 #include <sys/vnode.h>
76
77 #include <vm/vm.h>
78 #include <vm/vm_kern.h>
79 #include <vm/pmap.h>
80 #include <vm/vm_extern.h>
81
82 #if (__FreeBSD_version >=400000)
83 #include <sys/bus.h> /* used by smbus and newbus */
84 #endif
85
86 #if (__FreeBSD_version >=300000)
87 #include <machine/bus_memio.h> /* used by bus space */
88 #include <machine/bus.h> /* used by bus space and newbus */
89 #include <sys/bus.h>
90 #endif
91
92 #if (__FreeBSD_version >=400000)
93 #include <sys/rman.h> /* used by newbus */
94 #include <machine/resource.h> /* used by newbus */
95 #endif
96
97 #if (__FreeBSD_version < 500000)
98 #include <machine/clock.h> /* for DELAY */
99 #endif
100
101 #include <pci/pcivar.h>
102 #include <pci/pcireg.h>
103
104 #include <sys/sysctl.h>
105 int bt848_card = -1;
106 int bt848_tuner = -1;
107 int bt848_reverse_mute = -1;
108 int bt848_format = -1;
109 int bt848_slow_msp_audio = -1;
110
111 SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
112 SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
113 SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
114 SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
115 SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
116 SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
117
118 #endif /* end freebsd section */
119
120
121
122 /****************/
123 /* *** BSDI *** */
124 /****************/
125 #ifdef __bsdi__
126 #endif /* __bsdi__ */
127
128
129 /**************************/
130 /* *** OpenBSD/NetBSD *** */
131 /**************************/
132 #if defined(__NetBSD__) || defined(__OpenBSD__)
133
134 #include <sys/param.h>
135 #include <sys/systm.h>
136 #include <sys/conf.h>
137 #include <sys/uio.h>
138 #include <sys/kernel.h>
139 #include <sys/signalvar.h>
140 #include <sys/mman.h>
141 #include <sys/poll.h>
142 #include <sys/select.h>
143 #include <sys/vnode.h>
144
145 #include <vm/vm.h>
146
147 #ifndef __NetBSD__
148 #include <vm/vm_kern.h>
149 #include <vm/pmap.h>
150 #include <vm/vm_extern.h>
151 #endif
152
153 #include <sys/device.h>
154 #include <dev/pci/pcivar.h>
155 #include <dev/pci/pcireg.h>
156 #include <dev/pci/pcidevs.h>
157
158 #define BKTR_DEBUG
159 #ifdef BKTR_DEBUG
160 int bktr_debug = 0;
161 #define DPR(x) (bktr_debug ? printf x : 0)
162 #else
163 #define DPR(x)
164 #endif
165 #endif /* __NetBSD__ || __OpenBSD__ */
166
167
168 #ifdef __NetBSD__
169 #include <dev/ic/bt8xx.h> /* NetBSD location for .h files */
170 #include <dev/pci/bktr/bktr_reg.h>
171 #include <dev/pci/bktr/bktr_tuner.h>
172 #include <dev/pci/bktr/bktr_card.h>
173 #include <dev/pci/bktr/bktr_audio.h>
174 #include <dev/pci/bktr/bktr_core.h>
175 #include <dev/pci/bktr/bktr_os.h>
176 #else /* Traditional location for .h files */
177 #include <machine/ioctl_meteor.h>
178 #include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
179 #include <dev/bktr/bktr_reg.h>
180 #include <dev/bktr/bktr_tuner.h>
181 #include <dev/bktr/bktr_card.h>
182 #include <dev/bktr/bktr_audio.h>
183 #include <dev/bktr/bktr_core.h>
184 #include <dev/bktr/bktr_os.h>
185
186 #if defined(BKTR_USE_FREEBSD_SMBUS)
187 #include <dev/bktr/bktr_i2c.h>
188
189 #include "iicbb_if.h"
190 #include "smbus_if.h"
191 #endif
192 #endif
193
194
195 /****************************/
196 /* *** FreeBSD 4.x code *** */
197 /****************************/
198 #if (__FreeBSD_version >= 400000)
199
200 static int bktr_probe( device_t dev );
201 static int bktr_attach( device_t dev );
202 static int bktr_detach( device_t dev );
203 static int bktr_shutdown( device_t dev );
204 static void bktr_intr(void *arg) { common_bktr_intr(arg); }
205
206 static device_method_t bktr_methods[] = {
207 /* Device interface */
208 DEVMETHOD(device_probe, bktr_probe),
209 DEVMETHOD(device_attach, bktr_attach),
210 DEVMETHOD(device_detach, bktr_detach),
211 DEVMETHOD(device_shutdown, bktr_shutdown),
212
213 #if defined(BKTR_USE_FREEBSD_SMBUS)
214 /* iicbb interface */
215 DEVMETHOD(iicbb_callback, bti2c_iic_callback),
216 DEVMETHOD(iicbb_setsda, bti2c_iic_setsda),
217 DEVMETHOD(iicbb_setscl, bti2c_iic_setscl),
218 DEVMETHOD(iicbb_getsda, bti2c_iic_getsda),
219 DEVMETHOD(iicbb_getscl, bti2c_iic_getscl),
220 DEVMETHOD(iicbb_reset, bti2c_iic_reset),
221
222 /* smbus interface */
223 DEVMETHOD(smbus_callback, bti2c_smb_callback),
224 DEVMETHOD(smbus_writeb, bti2c_smb_writeb),
225 DEVMETHOD(smbus_writew, bti2c_smb_writew),
226 DEVMETHOD(smbus_readb, bti2c_smb_readb),
227 #endif
228
229 { 0, 0 }
230 };
231
232 static driver_t bktr_driver = {
233 "bktr",
234 bktr_methods,
235 sizeof(struct bktr_softc),
236 };
237
238 static devclass_t bktr_devclass;
239
240 static d_open_t bktr_open;
241 static d_close_t bktr_close;
242 static d_read_t bktr_read;
243 static d_write_t bktr_write;
244 static d_ioctl_t bktr_ioctl;
245 static d_mmap_t bktr_mmap;
246 static d_poll_t bktr_poll;
247
248 #define CDEV_MAJOR 92
249 static struct cdevsw bktr_cdevsw = {
250 .d_open = bktr_open,
251 .d_close = bktr_close,
252 .d_read = bktr_read,
253 .d_write = bktr_write,
254 .d_ioctl = bktr_ioctl,
255 .d_poll = bktr_poll,
256 .d_mmap = bktr_mmap,
257 .d_name = "bktr",
258 .d_maj = CDEV_MAJOR,
259 };
260
261 DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0);
262 #if (__FreeBSD_version > 410000)
263 MODULE_DEPEND(bktr, bktr_mem, 1,1,1);
264 MODULE_VERSION(bktr, 1);
265 #endif
266
267
268 /*
269 * the boot time probe routine.
270 */
271 static int
272 bktr_probe( device_t dev )
273 {
274 unsigned int type = pci_get_devid(dev);
275 unsigned int rev = pci_get_revid(dev);
276
277 if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE)
278 {
279 switch (PCI_PRODUCT(type)) {
280 case PCI_PRODUCT_BROOKTREE_BT848:
281 if (rev == 0x12)
282 device_set_desc(dev, "BrookTree 848A");
283 else
284 device_set_desc(dev, "BrookTree 848");
285 return 0;
286 case PCI_PRODUCT_BROOKTREE_BT849:
287 device_set_desc(dev, "BrookTree 849A");
288 return 0;
289 case PCI_PRODUCT_BROOKTREE_BT878:
290 device_set_desc(dev, "BrookTree 878");
291 return 0;
292 case PCI_PRODUCT_BROOKTREE_BT879:
293 device_set_desc(dev, "BrookTree 879");
294 return 0;
295 }
296 };
297
298 return ENXIO;
299 }
300
301
302 /*
303 * the attach routine.
304 */
305 static int
306 bktr_attach( device_t dev )
307 {
308 u_long latency;
309 u_long fun;
310 u_long val;
311 unsigned int rev;
312 unsigned int unit;
313 int error = 0;
314 #ifdef BROOKTREE_IRQ
315 u_long old_irq, new_irq;
316 #endif
317
318 struct bktr_softc *bktr = device_get_softc(dev);
319
320 unit = device_get_unit(dev);
321
322 /* build the device name for bktr_name() */
323 snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit);
324
325 /*
326 * Enable bus mastering and Memory Mapped device
327 */
328 val = pci_read_config(dev, PCIR_COMMAND, 4);
329 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
330 pci_write_config(dev, PCIR_COMMAND, val, 4);
331
332 /*
333 * Map control/status registers.
334 */
335 bktr->mem_rid = PCIR_MAPS;
336 bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid,
337 0, ~0, 1, RF_ACTIVE);
338
339
340 if (!bktr->res_mem) {
341 device_printf(dev, "could not map memory\n");
342 error = ENXIO;
343 goto fail;
344 }
345 bktr->memt = rman_get_bustag(bktr->res_mem);
346 bktr->memh = rman_get_bushandle(bktr->res_mem);
347
348
349 /*
350 * Disable the brooktree device
351 */
352 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
353 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
354
355
356 #ifdef BROOKTREE_IRQ /* from the configuration file */
357 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
358 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ);
359 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
360 printf("bktr%d: attach: irq changed from %d to %d\n",
361 unit, (old_irq & 0xff), (new_irq & 0xff));
362 #endif
363
364 /*
365 * Allocate our interrupt.
366 */
367 bktr->irq_rid = 0;
368 bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid,
369 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
370 if (bktr->res_irq == NULL) {
371 device_printf(dev, "could not map interrupt\n");
372 error = ENXIO;
373 goto fail;
374 }
375
376 error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY,
377 bktr_intr, bktr, &bktr->res_ih);
378 if (error) {
379 device_printf(dev, "could not setup irq\n");
380 goto fail;
381
382 }
383
384
385 /* Update the Device Control Register */
386 /* on Bt878 and Bt879 cards */
387 fun = pci_read_config( dev, 0x40, 2);
388 fun = fun | 1; /* Enable writes to the sub-system vendor ID */
389
390 #if defined( BKTR_430_FX_MODE )
391 if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n");
392 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */
393 #endif
394
395 #if defined( BKTR_SIS_VIA_MODE )
396 if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n");
397 fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for
398 OPTi chipset motherboards too */
399 #endif
400 pci_write_config(dev, 0x40, fun, 2);
401
402 #if defined(BKTR_USE_FREEBSD_SMBUS)
403 if (bt848_i2c_attach(dev))
404 printf("bktr%d: i2c_attach: can't attach\n", unit);
405 #endif
406
407 /*
408 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
409 * you have more than four, then 16 would probably be a better value.
410 */
411 #ifndef BROOKTREE_DEF_LATENCY_VALUE
412 #define BROOKTREE_DEF_LATENCY_VALUE 10
413 #endif
414 latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4);
415 latency = (latency >> 8) & 0xff;
416 if ( bootverbose ) {
417 if (latency)
418 printf("brooktree%d: PCI bus latency is", unit);
419 else
420 printf("brooktree%d: PCI bus latency was 0 changing to",
421 unit);
422 }
423 if ( !latency ) {
424 latency = BROOKTREE_DEF_LATENCY_VALUE;
425 pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4);
426 }
427 if ( bootverbose ) {
428 printf(" %d.\n", (int) latency);
429 }
430
431 /* read the pci device id and revision id */
432 fun = pci_get_devid(dev);
433 rev = pci_get_revid(dev);
434
435 /* call the common attach code */
436 common_bktr_attach( bktr, unit, fun, rev );
437
438 /* make the device entries */
439 bktr->bktrdev = make_dev(&bktr_cdevsw, unit,
440 0, 0, 0444, "bktr%d", unit);
441 bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16,
442 0, 0, 0444, "tuner%d", unit);
443 bktr->vbidev = make_dev(&bktr_cdevsw, unit+32,
444 0, 0, 0444, "vbi%d" , unit);
445
446
447 /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */
448 /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */
449 #if (__FreeBSD_version >=500000)
450 if (unit == 0) {
451 bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr");
452 bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner");
453 bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi");
454 }
455 #endif
456
457 return 0;
458
459 fail:
460 if (bktr->res_irq)
461 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
462 if (bktr->res_mem)
463 bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem);
464 return error;
465
466 }
467
468 /*
469 * the detach routine.
470 */
471 static int
472 bktr_detach( device_t dev )
473 {
474 unsigned int unit;
475
476 struct bktr_softc *bktr = device_get_softc(dev);
477
478 unit = device_get_unit(dev);
479
480 /* Disable the brooktree device */
481 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
482 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
483
484 #if defined(BKTR_USE_FREEBSD_SMBUS)
485 if (bt848_i2c_detach(dev))
486 printf("bktr%d: i2c_attach: can't attach\n", unit);
487 #endif
488
489 /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */
490 /* The memory is retained by the bktr_mem module so we can unload and */
491 /* then reload the main bktr driver module */
492
493 /* Unregister the /dev/bktrN, tunerN and vbiN devices,
494 * the aliases for unit 0 are automatically destroyed */
495 destroy_dev(bktr->vbidev);
496 destroy_dev(bktr->tunerdev);
497 destroy_dev(bktr->bktrdev);
498
499 /*
500 * Deallocate resources.
501 */
502 bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih);
503 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq);
504 bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem);
505
506 return 0;
507 }
508
509 /*
510 * the shutdown routine.
511 */
512 static int
513 bktr_shutdown( device_t dev )
514 {
515 struct bktr_softc *bktr = device_get_softc(dev);
516
517 /* Disable the brooktree device */
518 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
519 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
520
521 return 0;
522 }
523
524
525 /*
526 * Special Memory Allocation
527 */
528 vm_offset_t
529 get_bktr_mem( int unit, unsigned size )
530 {
531 vm_offset_t addr = 0;
532
533 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24);
534 if (addr == 0)
535 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE);
536 if (addr == 0) {
537 printf("bktr%d: Unable to allocate %d bytes of memory.\n",
538 unit, size);
539 }
540
541 return( addr );
542 }
543
544
545 /*---------------------------------------------------------
546 **
547 ** BrookTree 848 character device driver routines
548 **
549 **---------------------------------------------------------
550 */
551
552 #define VIDEO_DEV 0x00
553 #define TUNER_DEV 0x01
554 #define VBI_DEV 0x02
555
556 #define UNIT(x) ((x) & 0x0f)
557 #define FUNCTION(x) (x >> 4)
558
559 /*
560 *
561 */
562 static int
563 bktr_open( dev_t dev, int flags, int fmt, struct thread *td )
564 {
565 bktr_ptr_t bktr;
566 int unit;
567 int result;
568
569 unit = UNIT( minor(dev) );
570
571 /* Get the device data */
572 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
573 if (bktr == NULL) {
574 /* the device is no longer valid/functioning */
575 return (ENXIO);
576 }
577
578 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
579 return( ENXIO );
580
581 /* Record that the device is now busy */
582 device_busy(devclass_get_device(bktr_devclass, unit));
583
584
585 if (bt848_card != -1) {
586 if ((bt848_card >> 8 == unit ) &&
587 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) {
588 if ( bktr->bt848_card != (bt848_card & 0xff) ) {
589 bktr->bt848_card = (bt848_card & 0xff);
590 probeCard(bktr, FALSE, unit);
591 }
592 }
593 }
594
595 if (bt848_tuner != -1) {
596 if ((bt848_tuner >> 8 == unit ) &&
597 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) {
598 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) {
599 bktr->bt848_tuner = (bt848_tuner & 0xff);
600 probeCard(bktr, FALSE, unit);
601 }
602 }
603 }
604
605 if (bt848_reverse_mute != -1) {
606 if ((bt848_reverse_mute >> 8) == unit ) {
607 bktr->reverse_mute = bt848_reverse_mute & 0xff;
608 }
609 }
610
611 if (bt848_slow_msp_audio != -1) {
612 if ((bt848_slow_msp_audio >> 8) == unit ) {
613 bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
614 }
615 }
616
617 switch ( FUNCTION( minor(dev) ) ) {
618 case VIDEO_DEV:
619 result = video_open( bktr );
620 break;
621 case TUNER_DEV:
622 result = tuner_open( bktr );
623 break;
624 case VBI_DEV:
625 result = vbi_open( bktr );
626 break;
627 default:
628 result = ENXIO;
629 break;
630 }
631
632 /* If there was an error opening the device, undo the busy status */
633 if (result != 0)
634 device_unbusy(devclass_get_device(bktr_devclass, unit));
635 return( result );
636 }
637
638
639 /*
640 *
641 */
642 static int
643 bktr_close( dev_t dev, int flags, int fmt, struct thread *td )
644 {
645 bktr_ptr_t bktr;
646 int unit;
647 int result;
648
649 unit = UNIT( minor(dev) );
650
651 /* Get the device data */
652 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
653 if (bktr == NULL) {
654 /* the device is no longer valid/functioning */
655 return (ENXIO);
656 }
657
658 switch ( FUNCTION( minor(dev) ) ) {
659 case VIDEO_DEV:
660 result = video_close( bktr );
661 break;
662 case TUNER_DEV:
663 result = tuner_close( bktr );
664 break;
665 case VBI_DEV:
666 result = vbi_close( bktr );
667 break;
668 default:
669 return (ENXIO);
670 break;
671 }
672
673 device_unbusy(devclass_get_device(bktr_devclass, unit));
674 return( result );
675 }
676
677
678 /*
679 *
680 */
681 static int
682 bktr_read( dev_t dev, struct uio *uio, int ioflag )
683 {
684 bktr_ptr_t bktr;
685 int unit;
686
687 unit = UNIT(minor(dev));
688
689 /* Get the device data */
690 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
691 if (bktr == NULL) {
692 /* the device is no longer valid/functioning */
693 return (ENXIO);
694 }
695
696 switch ( FUNCTION( minor(dev) ) ) {
697 case VIDEO_DEV:
698 return( video_read( bktr, unit, dev, uio ) );
699 case VBI_DEV:
700 return( vbi_read( bktr, uio, ioflag ) );
701 }
702 return( ENXIO );
703 }
704
705
706 /*
707 *
708 */
709 static int
710 bktr_write( dev_t dev, struct uio *uio, int ioflag )
711 {
712 return( EINVAL ); /* XXX or ENXIO ? */
713 }
714
715
716 /*
717 *
718 */
719 static int
720 bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td )
721 {
722 bktr_ptr_t bktr;
723 int unit;
724
725 unit = UNIT(minor(dev));
726
727 /* Get the device data */
728 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
729 if (bktr == NULL) {
730 /* the device is no longer valid/functioning */
731 return (ENXIO);
732 }
733
734 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */
735 return( ENOMEM );
736
737 switch ( FUNCTION( minor(dev) ) ) {
738 case VIDEO_DEV:
739 return( video_ioctl( bktr, unit, cmd, arg, td ) );
740 case TUNER_DEV:
741 return( tuner_ioctl( bktr, unit, cmd, arg, td ) );
742 }
743
744 return( ENXIO );
745 }
746
747
748 /*
749 *
750 */
751 static int
752 bktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot )
753 {
754 int unit;
755 bktr_ptr_t bktr;
756
757 unit = UNIT(minor(dev));
758
759 if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */
760 return( -1 );
761
762 /* Get the device data */
763 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
764 if (bktr == NULL) {
765 /* the device is no longer valid/functioning */
766 return (ENXIO);
767 }
768
769 if (nprot & PROT_EXEC)
770 return( -1 );
771
772 if (offset < 0)
773 return( -1 );
774
775 if (offset >= bktr->alloc_pages * PAGE_SIZE)
776 return( -1 );
777
778 *paddr = vtophys(bktr->bigbuf) + offset;
779 return( 0 );
780 }
781
782 static int
783 bktr_poll( dev_t dev, int events, struct thread *td)
784 {
785 int unit;
786 bktr_ptr_t bktr;
787 int revents = 0;
788 DECLARE_INTR_MASK(s);
789
790 unit = UNIT(minor(dev));
791
792 /* Get the device data */
793 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit);
794 if (bktr == NULL) {
795 /* the device is no longer valid/functioning */
796 return (ENXIO);
797 }
798
799 DISABLE_INTR(s);
800
801 if (events & (POLLIN | POLLRDNORM)) {
802
803 switch ( FUNCTION( minor(dev) ) ) {
804 case VBI_DEV:
805 if(bktr->vbisize == 0)
806 selrecord(td, &bktr->vbi_select);
807 else
808 revents |= events & (POLLIN | POLLRDNORM);
809 break;
810 }
811 }
812
813 ENABLE_INTR(s);
814
815 return (revents);
816 }
817
818 #endif /* FreeBSD 4.x specific kernel interface routines */
819
820 /*****************/
821 /* *** BSDI *** */
822 /*****************/
823
824 #if defined(__bsdi__)
825 #endif /* __bsdi__ BSDI specific kernel interface routines */
826
827
828 /*****************************/
829 /* *** OpenBSD / NetBSD *** */
830 /*****************************/
831 #if defined(__NetBSD__) || defined(__OpenBSD__)
832
833 #define IPL_VIDEO IPL_BIO /* XXX */
834
835 static int bktr_intr(void *arg) { return common_bktr_intr(arg); }
836
837 #define bktr_open bktropen
838 #define bktr_close bktrclose
839 #define bktr_read bktrread
840 #define bktr_write bktrwrite
841 #define bktr_ioctl bktrioctl
842 #define bktr_mmap bktrmmap
843
844 vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
845 vm_offset_t, vm_offset_t);
846
847 #if defined(__OpenBSD__)
848 static int bktr_probe(struct device *, void *, void *);
849 #else
850 static int bktr_probe(struct device *, struct cfdata *, void *);
851 #endif
852 static void bktr_attach(struct device *, struct device *, void *);
853
854 struct cfattach bktr_ca = {
855 sizeof(struct bktr_softc), bktr_probe, bktr_attach
856 };
857
858 #if defined(__NetBSD__)
859 extern struct cfdriver bktr_cd;
860 #else
861 struct cfdriver bktr_cd = {
862 NULL, "bktr", DV_DULL
863 };
864 #endif
865
866 int
867 bktr_probe(parent, match, aux)
868 struct device *parent;
869 #if defined(__OpenBSD__)
870 void *match;
871 #else
872 struct cfdata *match;
873 #endif
874 void *aux;
875 {
876 struct pci_attach_args *pa = aux;
877
878 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
879 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
880 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
881 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
882 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
883 return 1;
884
885 return 0;
886 }
887
888
889 /*
890 * the attach routine.
891 */
892 static void
893 bktr_attach(struct device *parent, struct device *self, void *aux)
894 {
895 bktr_ptr_t bktr;
896 u_long latency;
897 u_long fun;
898 unsigned int rev;
899
900 #if defined(__OpenBSD__)
901 struct pci_attach_args *pa = aux;
902 pci_chipset_tag_t pc = pa->pa_pc;
903
904 pci_intr_handle_t ih;
905 const char *intrstr;
906 int retval;
907 int unit;
908
909 bktr = (bktr_ptr_t)self;
910 unit = bktr->bktr_dev.dv_unit;
911
912 bktr->pc = pa->pa_pc;
913 bktr->tag = pa->pa_tag;
914 bktr->dmat = pa->pa_dmat;
915
916 /*
917 * map memory
918 */
919 bktr->memt = pa->pa_memt;
920 retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START,
921 &bktr->phys_base, &bktr->obmemsz, NULL);
922 if (!retval)
923 retval = bus_space_map(pa->pa_memt, bktr->phys_base,
924 bktr->obmemsz, 0, &bktr->memh);
925 if (retval) {
926 printf(": couldn't map memory\n");
927 return;
928 }
929
930
931 /*
932 * map interrupt
933 */
934 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
935 pa->pa_intrline, &ih)) {
936 printf(": couldn't map interrupt\n");
937 return;
938 }
939 intrstr = pci_intr_string(pa->pa_pc, ih);
940
941 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
942 bktr_intr, bktr, bktr->bktr_dev.dv_xname);
943 if (bktr->ih == NULL) {
944 printf(": couldn't establish interrupt");
945 if (intrstr != NULL)
946 printf(" at %s", intrstr);
947 printf("\n");
948 return;
949 }
950
951 if (intrstr != NULL)
952 printf(": %s\n", intrstr);
953 #endif /* __OpenBSD__ */
954
955 #if defined(__NetBSD__)
956 struct pci_attach_args *pa = aux;
957 pci_intr_handle_t ih;
958 const char *intrstr;
959 int retval;
960 int unit;
961
962 bktr = (bktr_ptr_t)self;
963 unit = bktr->bktr_dev.dv_unit;
964 bktr->dmat = pa->pa_dmat;
965
966 printf("\n");
967
968 /*
969 * map memory
970 */
971 retval = pci_mapreg_map(pa, PCI_MAPREG_START,
972 PCI_MAPREG_TYPE_MEM
973 | PCI_MAPREG_MEM_TYPE_32BIT, 0,
974 &bktr->memt, &bktr->memh, NULL,
975 &bktr->obmemsz);
976 DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n",
977 bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz));
978 if (retval) {
979 printf("%s: couldn't map memory\n", bktr_name(bktr));
980 return;
981 }
982
983 /*
984 * Disable the brooktree device
985 */
986 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
987 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
988
989 /*
990 * map interrupt
991 */
992 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
993 pa->pa_intrline, &ih)) {
994 printf("%s: couldn't map interrupt\n",
995 bktr_name(bktr));
996 return;
997 }
998 intrstr = pci_intr_string(pa->pa_pc, ih);
999 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
1000 bktr_intr, bktr);
1001 if (bktr->ih == NULL) {
1002 printf("%s: couldn't establish interrupt",
1003 bktr_name(bktr));
1004 if (intrstr != NULL)
1005 printf(" at %s", intrstr);
1006 printf("\n");
1007 return;
1008 }
1009 if (intrstr != NULL)
1010 printf("%s: interrupting at %s\n", bktr_name(bktr),
1011 intrstr);
1012 #endif /* __NetBSD__ */
1013
1014 /*
1015 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
1016 * you have more than four, then 16 would probably be a better value.
1017 */
1018 #ifndef BROOKTREE_DEF_LATENCY_VALUE
1019 #define BROOKTREE_DEF_LATENCY_VALUE 10
1020 #endif
1021 latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
1022 latency = (latency >> 8) & 0xff;
1023
1024 if (!latency) {
1025 if (bootverbose) {
1026 printf("%s: PCI bus latency was 0 changing to %d",
1027 bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE);
1028 }
1029 latency = BROOKTREE_DEF_LATENCY_VALUE;
1030 pci_conf_write(pa->pa_pc, pa->pa_tag,
1031 PCI_LATENCY_TIMER, latency<<8);
1032 }
1033
1034
1035 /* Enabled Bus Master
1036 XXX: check if all old DMA is stopped first (e.g. after warm
1037 boot) */
1038 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
1039 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
1040 fun | PCI_COMMAND_MASTER_ENABLE);
1041
1042 /* read the pci id and determine the card type */
1043 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
1044 rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff;
1045
1046 common_bktr_attach(bktr, unit, fun, rev);
1047 }
1048
1049
1050 /*
1051 * Special Memory Allocation
1052 */
1053 vm_offset_t
1054 get_bktr_mem(bktr, dmapp, size)
1055 bktr_ptr_t bktr;
1056 bus_dmamap_t *dmapp;
1057 unsigned int size;
1058 {
1059 bus_dma_tag_t dmat = bktr->dmat;
1060 bus_dma_segment_t seg;
1061 bus_size_t align;
1062 int rseg;
1063 caddr_t kva;
1064
1065 /*
1066 * Allocate a DMA area
1067 */
1068 align = 1 << 24;
1069 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1070 &rseg, BUS_DMA_NOWAIT)) {
1071 align = PAGE_SIZE;
1072 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
1073 &rseg, BUS_DMA_NOWAIT)) {
1074 printf("%s: Unable to dmamem_alloc of %d bytes\n",
1075 bktr_name(bktr), size);
1076 return 0;
1077 }
1078 }
1079 if (bus_dmamem_map(dmat, &seg, rseg, size,
1080 &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1081 printf("%s: Unable to dmamem_map of %d bytes\n",
1082 bktr_name(bktr), size);
1083 bus_dmamem_free(dmat, &seg, rseg);
1084 return 0;
1085 }
1086 #ifdef __OpenBSD__
1087 bktr->dm_mapsize = size;
1088 #endif
1089 /*
1090 * Create and locd the DMA map for the DMA area
1091 */
1092 if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
1093 printf("%s: Unable to dmamap_create of %d bytes\n",
1094 bktr_name(bktr), size);
1095 bus_dmamem_unmap(dmat, kva, size);
1096 bus_dmamem_free(dmat, &seg, rseg);
1097 return 0;
1098 }
1099 if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
1100 printf("%s: Unable to dmamap_load of %d bytes\n",
1101 bktr_name(bktr), size);
1102 bus_dmamem_unmap(dmat, kva, size);
1103 bus_dmamem_free(dmat, &seg, rseg);
1104 bus_dmamap_destroy(dmat, *dmapp);
1105 return 0;
1106 }
1107 return (vm_offset_t)kva;
1108 }
1109
1110 void
1111 free_bktr_mem(bktr, dmap, kva)
1112 bktr_ptr_t bktr;
1113 bus_dmamap_t dmap;
1114 vm_offset_t kva;
1115 {
1116 bus_dma_tag_t dmat = bktr->dmat;
1117
1118 #ifdef __NetBSD__
1119 bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
1120 #else
1121 bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize);
1122 #endif
1123 bus_dmamem_free(dmat, dmap->dm_segs, 1);
1124 bus_dmamap_destroy(dmat, dmap);
1125 }
1126
1127
1128 /*---------------------------------------------------------
1129 **
1130 ** BrookTree 848 character device driver routines
1131 **
1132 **---------------------------------------------------------
1133 */
1134
1135
1136 #define VIDEO_DEV 0x00
1137 #define TUNER_DEV 0x01
1138 #define VBI_DEV 0x02
1139
1140 #define UNIT(x) (minor((x) & 0x0f))
1141 #define FUNCTION(x) (minor((x >> 4) & 0x0f))
1142
1143 /*
1144 *
1145 */
1146 int
1147 bktr_open(dev_t dev, int flags, int fmt, struct thread *td)
1148 {
1149 bktr_ptr_t bktr;
1150 int unit;
1151
1152 unit = UNIT(dev);
1153
1154 /* unit out of range */
1155 if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
1156 return(ENXIO);
1157
1158 bktr = bktr_cd.cd_devs[unit];
1159
1160 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
1161 return(ENXIO);
1162
1163 switch (FUNCTION(dev)) {
1164 case VIDEO_DEV:
1165 return(video_open(bktr));
1166 case TUNER_DEV:
1167 return(tuner_open(bktr));
1168 case VBI_DEV:
1169 return(vbi_open(bktr));
1170 }
1171
1172 return(ENXIO);
1173 }
1174
1175
1176 /*
1177 *
1178 */
1179 int
1180 bktr_close(dev_t dev, int flags, int fmt, struct thread *td)
1181 {
1182 bktr_ptr_t bktr;
1183 int unit;
1184
1185 unit = UNIT(dev);
1186
1187 bktr = bktr_cd.cd_devs[unit];
1188
1189 switch (FUNCTION(dev)) {
1190 case VIDEO_DEV:
1191 return(video_close(bktr));
1192 case TUNER_DEV:
1193 return(tuner_close(bktr));
1194 case VBI_DEV:
1195 return(vbi_close(bktr));
1196 }
1197
1198 return(ENXIO);
1199 }
1200
1201 /*
1202 *
1203 */
1204 int
1205 bktr_read(dev_t dev, struct uio *uio, int ioflag)
1206 {
1207 bktr_ptr_t bktr;
1208 int unit;
1209
1210 unit = UNIT(dev);
1211
1212 bktr = bktr_cd.cd_devs[unit];
1213
1214 switch (FUNCTION(dev)) {
1215 case VIDEO_DEV:
1216 return(video_read(bktr, unit, dev, uio));
1217 case VBI_DEV:
1218 return(vbi_read(bktr, uio, ioflag));
1219 }
1220
1221 return(ENXIO);
1222 }
1223
1224
1225 /*
1226 *
1227 */
1228 int
1229 bktr_write(dev_t dev, struct uio *uio, int ioflag)
1230 {
1231 /* operation not supported */
1232 return(EOPNOTSUPP);
1233 }
1234
1235 /*
1236 *
1237 */
1238 int
1239 bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td)
1240 {
1241 bktr_ptr_t bktr;
1242 int unit;
1243
1244 unit = UNIT(dev);
1245
1246 bktr = bktr_cd.cd_devs[unit];
1247
1248 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */
1249 return(ENOMEM);
1250
1251 switch (FUNCTION(dev)) {
1252 case VIDEO_DEV:
1253 return(video_ioctl(bktr, unit, cmd, arg, pr));
1254 case TUNER_DEV:
1255 return(tuner_ioctl(bktr, unit, cmd, arg, pr));
1256 }
1257
1258 return(ENXIO);
1259 }
1260
1261 /*
1262 *
1263 */
1264 paddr_t
1265 bktr_mmap(dev_t dev, off_t offset, int nprot)
1266 {
1267 int unit;
1268 bktr_ptr_t bktr;
1269
1270 unit = UNIT(dev);
1271
1272 if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */
1273 return(-1);
1274
1275 bktr = bktr_cd.cd_devs[unit];
1276
1277 if ((vaddr_t)offset < 0)
1278 return(-1);
1279
1280 if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE)
1281 return(-1);
1282
1283 #ifdef __NetBSD__
1284 return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
1285 (vaddr_t)offset, nprot, BUS_DMA_WAITOK));
1286 #else
1287 return(i386_btop(vtophys(bktr->bigbuf) + offset));
1288 #endif
1289 }
1290
1291 #endif /* __NetBSD__ || __OpenBSD__ */
Cache object: a09e9e44200cce850bb334d05fb9c444
|