aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/bktr/bktr_os.c
diff options
context:
space:
mode:
authorRoger Hardiman <roger@FreeBSD.org>2000-04-04 16:54:13 +0000
committerRoger Hardiman <roger@FreeBSD.org>2000-04-04 16:54:13 +0000
commit24cf43ae215d8543917fa588a835061382110799 (patch)
treec708d92a00907a43a59ceb590fd25ebfdd6a89a9 /sys/dev/bktr/bktr_os.c
parentbcc862e3976f22cd559e392850ca062cfb23c08c (diff)
downloadsrc-24cf43ae215d8543917fa588a835061382110799.tar.gz
src-24cf43ae215d8543917fa588a835061382110799.zip
Upgrade the bktr driver from 2.07 to 2.10.
- The driver now uses bus_space() and runs on NetBSD 1.4.2 Submitted by Thomas Klausner <wiz@danbala.ifoer.tuwien.ac.at> - Remove startup quirks for video and vbi capture for PAL users. PAL TV users can now run FXTV and Alevt in any order. - Add support for cable channels >100 Submitted by Scott Presnell <srp@zgi.com> - New MSP3410/3415 setup code added. This is experimental. Please set the sysctl hw.bt848.slow_msp_audio to 1 for this. Submitted by Frank Nobis<fn@radio-do.de>
Notes
Notes: svn path=/head/; revision=59014
Diffstat (limited to 'sys/dev/bktr/bktr_os.c')
-rw-r--r--sys/dev/bktr/bktr_os.c583
1 files changed, 545 insertions, 38 deletions
diff --git a/sys/dev/bktr/bktr_os.c b/sys/dev/bktr/bktr_os.c
index af7948ca698e..12d0c29d1b0b 100644
--- a/sys/dev/bktr/bktr_os.c
+++ b/sys/dev/bktr/bktr_os.c
@@ -50,14 +50,10 @@
#ifdef __FreeBSD__
#include "bktr.h"
-#include "opt_bktr.h"
#include "opt_devfs.h"
#endif /* __FreeBSD__ */
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#include "bktr.h"
-#include "pci.h"
-#endif /* __NetBSD__ || __OpenBSD__ */
+#include "opt_bktr.h" /* include any kernel config options */
#define FIFO_RISC_DISABLED 0
#define ALL_INTS_DISABLED 0
@@ -93,18 +89,30 @@
#include <sys/bus.h> /* used by smbus and newbus */
#endif
+#if (__FreeBSD_version >=300000)
+#include <machine/bus_memio.h> /* used by bus space */
+#include <machine/bus.h> /* used by bus space and newbus */
+#include <sys/bus.h>
+#endif
+
#if (__FreeBSD_version >=400000)
-#include <machine/bus.h> /* used by newbus */
#include <sys/rman.h> /* used by newbus */
#include <machine/resource.h> /* used by newbus */
#endif
+
#include <machine/clock.h> /* for DELAY */
#include <pci/pcivar.h>
#include <pci/pcireg.h>
+#endif
+#ifdef __NetBSD__
+#include <dev/ic/ioctl_meteor.h> /* NetBSD location for .h files */
+#include <dev/ic/ioctl_bt848.h>
+#else /* Traditional location for .h files */
#include <machine/ioctl_meteor.h>
#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */
+#endif
#include <dev/bktr/bktr_reg.h>
#include <dev/bktr/bktr_tuner.h>
#include <dev/bktr/bktr_card.h>
@@ -112,6 +120,7 @@
#include <dev/bktr/bktr_core.h>
#include <dev/bktr/bktr_os.h>
+#if defined(__FreeBSD__)
#if (NSMBUS > 0)
#include <dev/bktr/bktr_i2c.h>
#endif
@@ -121,22 +130,19 @@ int bt848_card = -1;
int bt848_tuner = -1;
int bt848_reverse_mute = -1;
int bt848_format = -1;
+int bt848_slow_msp_audio = -1;
SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt");
SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, "");
SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, "");
SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, "");
SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, "");
-
-#if (__FreeBSD_version >= 300000)
- typedef u_long ioctl_cmd_t;
+SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, "");
#endif
#if (__FreeBSD__ == 2)
-typedef int ioctl_cmd_t;
#define PCIR_REVID PCI_CLASS_REG
#endif
-#endif /* __FreeBSD__ */
/****************/
@@ -150,6 +156,21 @@ typedef int ioctl_cmd_t;
/* *** OpenBSD/NetBSD *** */
/**************************/
#if defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/device.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+static int bootverbose = 1;
+
+
+#define BKTR_DEBUG
+#ifdef BKTR_DEBUG
+int bktr_debug = 0;
+#define DPR(x) (bktr_debug ? printf x : 0)
+#else
+#define DPR(x)
+#endif
#endif /* __NetBSD__ || __OpenBSD__ */
@@ -247,7 +268,6 @@ bktr_probe( device_t dev )
static int
bktr_attach( device_t dev )
{
- bt848_ptr_t bt848;
u_long latency;
u_long fun;
u_long val;
@@ -282,14 +302,15 @@ bktr_attach( device_t dev )
error = ENXIO;
goto fail;
}
- bktr->base = rman_get_virtual(bktr->res_mem); /* XXX use bus_space */
+ bktr->memt = rman_get_bustag(bktr->res_mem);
+ bktr->memh = rman_get_bushandle(bktr->res_mem);
+
/*
* Disable the brooktree device
*/
- bt848 = bktr->base;
- bt848->int_mask = ALL_INTS_DISABLED;
- bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
+ OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
+ OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
#ifdef BROOKTREE_IRQ /* from the configuration file */
@@ -341,7 +362,7 @@ bktr_attach( device_t dev )
/* XXX call bt848_i2c dependent attach() routine */
#if (NSMBUS > 0)
- if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc))
+ if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc))
printf("bktr%d: i2c_attach: can't attach\n", unit);
#endif
@@ -395,12 +416,10 @@ static int
bktr_detach( device_t dev )
{
struct bktr_softc *bktr = device_get_softc(dev);
- bt848_ptr_t bt848;
/* Disable the brooktree device */
- bt848 = bktr->base;
- bt848->int_mask = ALL_INTS_DISABLED;
- bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
+ OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
+ OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
/* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */
@@ -421,12 +440,10 @@ static int
bktr_shutdown( device_t dev )
{
struct bktr_softc *bktr = device_get_softc(dev);
- bt848_ptr_t bt848;
/* Disable the brooktree device */
- bt848 = bktr->base;
- bt848->int_mask = ALL_INTS_DISABLED;
- bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
+ OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
+ OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
return 0;
}
@@ -513,10 +530,14 @@ bktr_open( dev_t dev, int flags, int fmt, struct proc *p )
}
if (bt848_reverse_mute != -1) {
- if (((bt848_reverse_mute >> 8) == unit ) &&
- ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) {
+ if ((bt848_reverse_mute >> 8) == unit ) {
bktr->reverse_mute = bt848_reverse_mute & 0xff;
- bt848_reverse_mute = -1;
+ }
+ }
+
+ if (bt848_slow_msp_audio != -1) {
+ if ((bt848_slow_msp_audio >> 8) == unit ) {
+ bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
}
}
@@ -806,10 +827,10 @@ static void
bktr_attach( pcici_t tag, int unit )
{
bktr_ptr_t bktr;
- bt848_ptr_t bt848;
u_long latency;
u_long fun;
unsigned int rev;
+ unsigned long base;
#ifdef BROOKTREE_IRQ
u_long old_irq, new_irq;
#endif
@@ -837,15 +858,18 @@ bktr_attach( pcici_t tag, int unit )
/*
* Map control/status registers
*/
- pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &bktr->base,
+ pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base,
&bktr->phys_base );
+#if (__FreeBSD_version >= 300000)
+ bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */
+ bktr->memh = (bus_space_handle_t)base; /* XXX functions here */
+#endif
/*
* Disable the brooktree device
*/
- bt848 = bktr->base;
- bt848->int_mask = ALL_INTS_DISABLED;
- bt848->gpio_dma_ctl = FIFO_RISC_DISABLED;
+ OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
+ OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
#ifdef BROOKTREE_IRQ /* from the configuration file */
old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG);
@@ -881,7 +905,7 @@ bktr_attach( pcici_t tag, int unit )
/* XXX call bt848_i2c dependent attach() routine */
#if (NSMBUS > 0)
- if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc))
+ if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc))
printf("bktr%d: i2c_attach: can't attach\n", unit);
#endif
@@ -1005,13 +1029,16 @@ bktr_open( dev_t dev, int flags, int fmt, struct proc *p )
}
if (bt848_reverse_mute != -1) {
- if (((bt848_reverse_mute >> 8) == unit ) &&
- ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) {
+ if ((bt848_reverse_mute >> 8) == unit ) {
bktr->reverse_mute = bt848_reverse_mute & 0xff;
- bt848_reverse_mute = -1;
}
}
+ if (bt848_slow_msp_audio != -1) {
+ if ((bt848_slow_msp_audio >> 8) == unit ) {
+ bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff);
+ }
+ }
switch ( FUNCTION( minor(dev) ) ) {
case VIDEO_DEV:
@@ -1192,5 +1219,485 @@ int bktr_poll( dev_t dev, int events, struct proc *p)
/* *** OpenBSD / NetBSD *** */
/*****************************/
#if defined(__NetBSD__) || defined(__OpenBSD__)
-#endif /* __NetBSD__ || __OpenBSD__ */
+
+#define IPL_VIDEO IPL_BIO /* XXX */
+
+static int bktr_intr(void *arg) { return common_bktr_intr(arg); }
+
+#define bktr_open bktropen
+#define bktr_close bktrclose
+#define bktr_read bktrread
+#define bktr_write bktrwrite
+#define bktr_ioctl bktrioctl
+#define bktr_mmap bktrmmap
+
+int bktr_open __P((dev_t, int, int, struct proc *));
+int bktr_close __P((dev_t, int, int, struct proc *));
+int bktr_read __P((dev_t, struct uio *, int));
+int bktr_write __P((dev_t, struct uio *, int));
+int bktr_ioctl __P((dev_t, ioctl_cmd_t, caddr_t, int, struct proc*));
+int bktr_mmap __P((dev_t, vm_offset_t, int));
+
+vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t,
+ vm_offset_t, vm_offset_t);
+
+#if defined(__BROKEN_INDIRECT_CONFIG) || defined(__OpenBSD__)
+static int bktr_probe __P((struct device *, void *, void *));
+#else
+static int bktr_probe __P((struct device *, struct cfdata *, void *));
+#endif
+static void bktr_attach __P((struct device *, struct device *, void *));
+
+struct cfattach bktr_ca = {
+ sizeof(struct bktr_softc), bktr_probe, bktr_attach
+};
+
+#if defined(__NetBSD__)
+extern struct cfdriver bktr_cd;
+#else
+struct cfdriver bktr_cd = {
+ NULL, "bktr", DV_DULL
+};
+#endif
+
+int bktr_probe(parent, match, aux)
+ struct device *parent;
+#if defined(__BROKEN_INDIRECT_CONFIG) || defined(__OpenBSD__)
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE &&
+ (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+ * the attach routine.
+ */
+static void
+bktr_attach __P((struct device *parent, struct device *self, void *aux))
+{
+ bktr_ptr_t bktr;
+ u_long latency;
+ u_long fun;
+ unsigned int rev;
+
+#if defined(__OpenBSD__)
+ struct pci_attach_args *pa = aux;
+ pci_chipset_tag_t pc = pa->pa_pc;
+
+ pci_intr_handle_t ih;
+ const char *intrstr;
+ int retval;
+ int unit;
+
+ bktr = (bktr_ptr_t)self;
+ unit = bktr->bktr_dev.dv_unit;
+
+ bktr->pc = pa->pa_pc;
+ bktr->tag = pa->pa_tag;
+ bktr->dmat = pa->pa_dmat;
+
+ /*
+ * map memory
+ */
+ bktr->memt = pa->pa_memt;
+ retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START,
+ &bktr->phys_base, &bktr->obmemsz, NULL);
+ if (!retval)
+ retval = bus_space_map(pa->pa_memt, bktr->phys_base,
+ bktr->obmemsz, 0, &bktr->memh);
+ if (retval) {
+ printf(": couldn't map memory\n");
+ return;
+ }
+
+
+ /*
+ * map interrupt
+ */
+ if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &ih)) {
+ printf(": couldn't map interrupt\n");
+ return;
+ }
+ intrstr = pci_intr_string(pa->pa_pc, ih);
+
+ bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
+ bktr_intr, bktr, bktr->bktr_dev.dv_xname);
+ if (bktr->ih == NULL) {
+ printf(": couldn't establish interrupt");
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+
+ if (intrstr != NULL)
+ printf(": %s\n", intrstr);
+#endif /* __OpenBSD__ */
+
+#if defined(__NetBSD__)
+ struct pci_attach_args *pa = aux;
+ pci_intr_handle_t ih;
+ const char *intrstr;
+ int retval;
+ int unit;
+
+ bktr = (bktr_ptr_t)self;
+ unit = bktr->bktr_dev.dv_unit;
+ bktr->dmat = pa->pa_dmat;
+
+ printf("\n");
+
+ /*
+ * map memory
+ */
+ retval = pci_mapreg_map(pa, PCI_MAPREG_START,
+ PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
+ &bktr->memt, &bktr->memh, &bktr->phys_base,
+ &bktr->obmemsz);
+ DPR(("pci_mapreg_map: memt %x, memh %x, base %x, size %x\n",
+ bktr->memt, (u_int)bktr->memh,
+ (u_int)bktr->phys_base, (u_int)bktr->obmemsz));
+ if (retval) {
+ printf("%s: couldn't map memory\n", bktr->bktr_dev.dv_xname);
+ return;
+ }
+
+ /*
+ * Disable the brooktree device
+ */
+ OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED);
+ OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED);
+
+ /*
+ * map interrupt
+ */
+ if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
+ pa->pa_intrline, &ih)) {
+ printf("%s: couldn't map interrupt\n", bktr->bktr_dev.dv_xname);
+ return;
+ }
+ intrstr = pci_intr_string(pa->pa_pc, ih);
+ bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO,
+ bktr_intr, bktr);
+ if (bktr->ih == NULL) {
+ printf("%s: couldn't establish interrupt",
+ bktr->bktr_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ return;
+ }
+ if (intrstr != NULL)
+ printf("%s: interrupting at %s\n", bktr->bktr_dev.dv_xname,
+ intrstr);
+#endif /* __NetBSD__ */
+
+/*
+ * PCI latency timer. 32 is a good value for 4 bus mastering slots, if
+ * you have more than four, then 16 would probably be a better value.
+ */
+#ifndef BROOKTREE_DEF_LATENCY_VALUE
+#define BROOKTREE_DEF_LATENCY_VALUE 10
+#endif
+ latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER);
+ latency = (latency >> 8) & 0xff;
+
+ if ( !latency ) {
+ if ( bootverbose ) {
+ printf("%s: PCI bus latency was 0 changing to %d",
+ bktr->bktr_dev.dv_xname,
+ BROOKTREE_DEF_LATENCY_VALUE);
+ }
+ latency = BROOKTREE_DEF_LATENCY_VALUE;
+ pci_conf_write(pa->pa_pc, pa->pa_tag,
+ PCI_LATENCY_TIMER, latency<<8);
+ }
+
+
+ /* Enabled Bus Master and Memory Mapping */
+ fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, fun | 2);
+ fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, fun | 4);
+
+ /* read the pci id and determine the card type */
+ fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG);
+ rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff;
+
+ common_bktr_attach( bktr, unit, fun, rev );
+}
+
+
+/*
+ * Special Memory Allocation
+ */
+vm_offset_t
+get_bktr_mem(bktr, dmapp, size)
+ bktr_ptr_t bktr;
+ bus_dmamap_t *dmapp;
+ unsigned int size;
+{
+ bus_dma_tag_t dmat = bktr->dmat;
+ bus_dma_segment_t seg;
+ bus_size_t align;
+ int rseg;
+ caddr_t kva;
+
+ /*
+ * Allocate a DMA area
+ */
+ align = 1 << 24;
+ if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
+ &rseg, BUS_DMA_NOWAIT)) {
+ align = PAGE_SIZE;
+ if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1,
+ &rseg, BUS_DMA_NOWAIT)) {
+ printf("bktr%d: Unable to dmamem_alloc of %d bytes\n",
+ bktr->bktr_dev.dv_unit, size);
+ return 0;
+ }
+ }
+ if (bus_dmamem_map(dmat, &seg, rseg, size,
+ &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
+ printf("bktr%d: Unable to dmamem_map of %d bytes\n",
+ bktr->bktr_dev.dv_unit, size);
+ bus_dmamem_free(dmat, &seg, rseg);
+ return 0;
+ }
+#ifdef __OpenBSD__
+ bktr->dm_mapsize = size;
+#endif
+ /*
+ * Create and locd the DMA map for the DMA area
+ */
+ if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) {
+ printf("bktr%d: Unable to dmamap_create of %d bytes\n",
+ bktr->bktr_dev.dv_unit, size);
+ bus_dmamem_unmap(dmat, kva, size);
+ bus_dmamem_free(dmat, &seg, rseg);
+ return 0;
+ }
+ if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) {
+ printf("bktr%d: Unable to dmamap_load of %d bytes\n",
+ bktr->bktr_dev.dv_unit, size);
+ bus_dmamem_unmap(dmat, kva, size);
+ bus_dmamem_free(dmat, &seg, rseg);
+ bus_dmamap_destroy(dmat, *dmapp);
+ return 0;
+ }
+ return (vm_offset_t)kva;
+}
+
+void
+free_bktr_mem(bktr, dmap, kva)
+ bktr_ptr_t bktr;
+ bus_dmamap_t dmap;
+ vm_offset_t kva;
+{
+ bus_dma_tag_t dmat = bktr->dmat;
+
+#ifdef __NetBSD__
+ bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize);
+#else
+ bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize);
+#endif
+ bus_dmamem_free(dmat, dmap->dm_segs, 1);
+ bus_dmamap_destroy(dmat, dmap);
+}
+
+
+/*---------------------------------------------------------
+**
+** BrookTree 848 character device driver routines
+**
+**---------------------------------------------------------
+*/
+
+
+#define VIDEO_DEV 0x00
+#define TUNER_DEV 0x01
+#define VBI_DEV 0x02
+
+#define UNIT(x) ((x) & 0x0f)
+#define FUNCTION(x) ((x >> 4) & 0x0f)
+
+/*
+ *
+ */
+int
+bktr_open( dev_t dev, int flags, int fmt, struct proc *p )
+{
+ bktr_ptr_t bktr;
+ int unit;
+
+ unit = UNIT( minor(dev) );
+
+ /* unit out of range */
+ if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
+ return( ENXIO );
+
+ bktr = bktr_cd.cd_devs[unit];
+
+
+ if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */
+ return( ENXIO );
+
+ switch ( FUNCTION( minor(dev) ) ) {
+ case VIDEO_DEV:
+ return( video_open( bktr ) );
+ case TUNER_DEV:
+ return( tuner_open( bktr ) );
+ case VBI_DEV:
+ return( vbi_open( bktr ) );
+ }
+
+ return( ENXIO );
+}
+
+
+/*
+ *
+ */
+int
+bktr_close( dev_t dev, int flags, int fmt, struct proc *p )
+{
+ bktr_ptr_t bktr;
+ int unit;
+
+ unit = UNIT( minor(dev) );
+
+ /* unit out of range */
+ if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
+ return( ENXIO );
+
+ bktr = bktr_cd.cd_devs[unit];
+
+ switch ( FUNCTION( minor(dev) ) ) {
+ case VIDEO_DEV:
+ return( video_close( bktr ) );
+ case TUNER_DEV:
+ return( tuner_close( bktr ) );
+ case VBI_DEV:
+ return( vbi_close( bktr ) );
+ }
+
+ return( ENXIO );
+}
+
+/*
+ *
+ */
+int
+bktr_read( dev_t dev, struct uio *uio, int ioflag )
+{
+ bktr_ptr_t bktr;
+ int unit;
+
+ unit = UNIT(minor(dev));
+
+ /* unit out of range */
+ if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
+ return( ENXIO );
+
+ bktr = bktr_cd.cd_devs[unit];
+
+ switch ( FUNCTION( minor(dev) ) ) {
+ case VIDEO_DEV:
+ return( video_read( bktr, unit, dev, uio ) );
+ case VBI_DEV:
+ return( vbi_read( bktr, uio, ioflag ) );
+ }
+
+ return( ENXIO );
+}
+
+
+/*
+ *
+ */
+int
+bktr_write( dev_t dev, struct uio *uio, int ioflag )
+{
+ /* operation not supported */
+ return( EOPNOTSUPP );
+}
+
+/*
+ *
+ */
+int
+bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr )
+{
+ bktr_ptr_t bktr;
+ int unit;
+
+ unit = UNIT(minor(dev));
+
+ /* unit out of range */
+ if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
+ return( ENXIO );
+
+ bktr = bktr_cd.cd_devs[unit];
+
+ if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */
+ return( ENOMEM );
+
+ switch ( FUNCTION( minor(dev) ) ) {
+ case VIDEO_DEV:
+ return( video_ioctl( bktr, unit, cmd, arg, pr ) );
+ case TUNER_DEV:
+ return( tuner_ioctl( bktr, unit, cmd, arg, pr ) );
+ }
+
+ return( ENXIO );
+}
+
+/*
+ *
+ */
+int
+bktr_mmap( dev_t dev, vm_offset_t offset, int nprot )
+{
+ int unit;
+ bktr_ptr_t bktr;
+
+ unit = UNIT(minor(dev));
+
+ /* unit out of range */
+ if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL))
+ return( -1 );
+ if (FUNCTION(minor(dev)) > 0)
+ return( -1 );
+
+ bktr = bktr_cd.cd_devs[unit];
+
+ if (offset < 0)
+ return( -1 );
+
+ if (offset >= bktr->alloc_pages * PAGE_SIZE)
+ return( -1 );
+
+#ifdef __NetBSD__
+ return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1,
+ offset, nprot, BUS_DMA_WAITOK));
+#else
+ return( i386_btop(vtophys(bktr->bigbuf) + offset) );
+#endif
+}
+
+#endif /* __NetBSD__ || __OpenBSD__ */