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