bktr_os.c revision 112569
1/* $FreeBSD: head/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>
105int bt848_card = -1;
106int bt848_tuner = -1;
107int bt848_reverse_mute = -1;
108int bt848_format = -1;
109int bt848_slow_msp_audio = -1;
110
111SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
112SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
113SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
114SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
115SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
116SYSCTL_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
160int 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
200static int	bktr_probe( device_t dev );
201static int	bktr_attach( device_t dev );
202static int	bktr_detach( device_t dev );
203static int	bktr_shutdown( device_t dev );
204static void	bktr_intr(void *arg) { common_bktr_intr(arg); }
205
206static 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
232static driver_t bktr_driver = {
233	"bktr",
234	bktr_methods,
235	sizeof(struct bktr_softc),
236};
237
238static devclass_t bktr_devclass;
239
240static	d_open_t	bktr_open;
241static	d_close_t	bktr_close;
242static	d_read_t	bktr_read;
243static	d_write_t	bktr_write;
244static	d_ioctl_t	bktr_ioctl;
245static	d_mmap_t	bktr_mmap;
246static	d_poll_t	bktr_poll;
247
248#define CDEV_MAJOR 92
249static 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
261DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0);
262#if (__FreeBSD_version > 410000)
263MODULE_DEPEND(bktr, bktr_mem, 1,1,1);
264MODULE_VERSION(bktr, 1);
265#endif
266
267
268/*
269 * the boot time probe routine.
270 */
271static int
272bktr_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 */
305static int
306bktr_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
459fail:
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 */
471static int
472bktr_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 */
512static int
513bktr_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 */
528vm_offset_t
529get_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 */
562static int
563bktr_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 */
642static int
643bktr_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 */
681static int
682bktr_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 */
709static int
710bktr_write( dev_t dev, struct uio *uio, int ioflag )
711{
712	return( EINVAL ); /* XXX or ENXIO ? */
713}
714
715
716/*
717 *
718 */
719static int
720bktr_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 */
751static int
752bktr_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
782static int
783bktr_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
835static	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
844vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
845                                 vm_offset_t, vm_offset_t);
846
847#if defined(__OpenBSD__)
848static int      bktr_probe(struct device *, void *, void *);
849#else
850static int      bktr_probe(struct device *, struct cfdata *, void *);
851#endif
852static void     bktr_attach(struct device *, struct device *, void *);
853
854struct cfattach bktr_ca = {
855        sizeof(struct bktr_softc), bktr_probe, bktr_attach
856};
857
858#if defined(__NetBSD__)
859extern struct cfdriver bktr_cd;
860#else
861struct cfdriver bktr_cd = {
862        NULL, "bktr", DV_DULL
863};
864#endif
865
866int
867bktr_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 */
892static void
893bktr_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 */
1053vm_offset_t
1054get_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
1110void
1111free_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 */
1146int
1147bktr_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 */
1179int
1180bktr_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 */
1204int
1205bktr_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 */
1228int
1229bktr_write(dev_t dev, struct uio *uio, int ioflag)
1230{
1231	/* operation not supported */
1232	return(EOPNOTSUPP);
1233}
1234
1235/*
1236 *
1237 */
1238int
1239bktr_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 */
1264paddr_t
1265bktr_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__ */
1292