bktr_os.c revision 62214
151694Sroger/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 62214 2000-06-28 15:09:12Z roger $ */ 251694Sroger 351694Sroger/* 451694Sroger * This is part of the Driver for Video Capture Cards (Frame grabbers) 551694Sroger * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 651694Sroger * chipset. 751694Sroger * Copyright Roger Hardiman and Amancio Hasty. 851694Sroger * 951694Sroger * bktr_os : This has all the Operating System dependant code, 1051694Sroger * probe/attach and open/close/ioctl/read/mmap 1151694Sroger * memory allocation 1251694Sroger * PCI bus interfacing 1351694Sroger * 1451694Sroger * 1551694Sroger */ 1651694Sroger 1751694Sroger/* 1851694Sroger * 1. Redistributions of source code must retain the 1951694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 2051694Sroger * All rights reserved. 2151694Sroger * 2251694Sroger * Redistribution and use in source and binary forms, with or without 2351694Sroger * modification, are permitted provided that the following conditions 2451694Sroger * are met: 2551694Sroger * 1. Redistributions of source code must retain the above copyright 2651694Sroger * notice, this list of conditions and the following disclaimer. 2751694Sroger * 2. Redistributions in binary form must reproduce the above copyright 2851694Sroger * notice, this list of conditions and the following disclaimer in the 2951694Sroger * documentation and/or other materials provided with the distribution. 3051694Sroger * 3. All advertising materials mentioning features or use of this software 3151694Sroger * must display the following acknowledgement: 3251694Sroger * This product includes software developed by Amancio Hasty and 3351694Sroger * Roger Hardiman 3451694Sroger * 4. The name of the author may not be used to endorse or promote products 3551694Sroger * derived from this software without specific prior written permission. 3651694Sroger * 3751694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 3851694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3951694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 4051694Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 4151694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 4251694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 4351694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4451694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4551694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 4651694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4751694Sroger * POSSIBILITY OF SUCH DAMAGE. 4851694Sroger */ 4951694Sroger 5051694Sroger 5151694Sroger#ifdef __FreeBSD__ 5251694Sroger#include "bktr.h" 5351694Sroger#include "opt_devfs.h" 5451694Sroger#endif /* __FreeBSD__ */ 5551694Sroger 5659014Sroger#include "opt_bktr.h" /* include any kernel config options */ 5751694Sroger 5851694Sroger#define FIFO_RISC_DISABLED 0 5951694Sroger#define ALL_INTS_DISABLED 0 6051694Sroger 6162214Sroger 6262214Sroger/*******************/ 6362214Sroger/* *** FreeBSD *** */ 6462214Sroger/*******************/ 6562214Sroger#ifdef __FreeBSD__ 6662214Sroger 6751694Sroger#include <sys/param.h> 6851694Sroger#include <sys/systm.h> 6951694Sroger#include <sys/conf.h> 7051694Sroger#include <sys/uio.h> 7151694Sroger#include <sys/kernel.h> 7251694Sroger#include <sys/signalvar.h> 7351694Sroger#include <sys/mman.h> 7451694Sroger#include <sys/poll.h> 7551694Sroger#include <sys/select.h> 7651694Sroger#include <sys/vnode.h> 7751694Sroger 7851694Sroger#include <vm/vm.h> 7951694Sroger#include <vm/vm_kern.h> 8051694Sroger#include <vm/pmap.h> 8151694Sroger#include <vm/vm_extern.h> 8251694Sroger 8351694Sroger#if (__FreeBSD_version < 400000) 8451694Sroger#ifdef DEVFS 8551694Sroger#include <sys/devfsext.h> 8651694Sroger#endif /* DEVFS */ 8751694Sroger#endif 8851694Sroger 8951694Sroger#if (__FreeBSD_version >=400000) || (NSMBUS > 0) 9051694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 9151694Sroger#endif 9251694Sroger 9359014Sroger#if (__FreeBSD_version >=300000) 9459014Sroger#include <machine/bus_memio.h> /* used by bus space */ 9559014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 9659014Sroger#include <sys/bus.h> 9759014Sroger#endif 9859014Sroger 9951694Sroger#if (__FreeBSD_version >=400000) 10051694Sroger#include <sys/rman.h> /* used by newbus */ 10151694Sroger#include <machine/resource.h> /* used by newbus */ 10251694Sroger#endif 10351694Sroger 10459014Sroger 10551694Sroger#include <machine/clock.h> /* for DELAY */ 10651694Sroger#include <pci/pcivar.h> 10751694Sroger#include <pci/pcireg.h> 10851694Sroger 10951694Sroger#if (NSMBUS > 0) 11051694Sroger#include <dev/bktr/bktr_i2c.h> 11151694Sroger#endif 11251694Sroger 11351694Sroger#include <sys/sysctl.h> 11451694Srogerint bt848_card = -1; 11551694Srogerint bt848_tuner = -1; 11651694Srogerint bt848_reverse_mute = -1; 11751694Srogerint bt848_format = -1; 11859014Srogerint bt848_slow_msp_audio = -1; 11951694Sroger 12051694SrogerSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 12151694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 12251694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 12351694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 12451694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 12559014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 12651694Sroger 12751694Sroger#if (__FreeBSD__ == 2) 12851694Sroger#define PCIR_REVID PCI_CLASS_REG 12951694Sroger#endif 13051694Sroger 13162214Sroger#endif /* end freebsd section */ 13251694Sroger 13362214Sroger 13462214Sroger 13551694Sroger/****************/ 13651694Sroger/* *** BSDI *** */ 13751694Sroger/****************/ 13851694Sroger#ifdef __bsdi__ 13951694Sroger#endif /* __bsdi__ */ 14051694Sroger 14151694Sroger 14251694Sroger/**************************/ 14351694Sroger/* *** OpenBSD/NetBSD *** */ 14451694Sroger/**************************/ 14551694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 14662214Sroger 14762214Sroger#include <sys/param.h> 14862214Sroger#include <sys/systm.h> 14962214Sroger#include <sys/conf.h> 15062214Sroger#include <sys/uio.h> 15162214Sroger#include <sys/kernel.h> 15262214Sroger#include <sys/signalvar.h> 15362214Sroger#include <sys/mman.h> 15462214Sroger#include <sys/poll.h> 15562214Sroger#include <sys/select.h> 15662214Sroger#include <sys/vnode.h> 15762214Sroger 15862214Sroger#include <vm/vm.h> 15962214Sroger 16062214Sroger#ifndef __NetBSD__ 16162214Sroger#include <vm/vm_kern.h> 16262214Sroger#include <vm/pmap.h> 16362214Sroger#include <vm/vm_extern.h> 16462214Sroger#endif 16562214Sroger 16659014Sroger#include <sys/device.h> 16759014Sroger#include <dev/pci/pcivar.h> 16859014Sroger#include <dev/pci/pcireg.h> 16959014Sroger#include <dev/pci/pcidevs.h> 17059014Sroger 17159014Sroger#define BKTR_DEBUG 17259014Sroger#ifdef BKTR_DEBUG 17359014Srogerint bktr_debug = 0; 17459014Sroger#define DPR(x) (bktr_debug ? printf x : 0) 17559014Sroger#else 17659014Sroger#define DPR(x) 17759014Sroger#endif 17851694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 17951694Sroger 18051694Sroger 18162214Sroger#ifdef __NetBSD__ 18262214Sroger#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 18362214Sroger#include <dev/pci/bktr/bktr_reg.h> 18462214Sroger#include <dev/pci/bktr/bktr_tuner.h> 18562214Sroger#include <dev/pci/bktr/bktr_card.h> 18662214Sroger#include <dev/pci/bktr/bktr_audio.h> 18762214Sroger#include <dev/pci/bktr/bktr_core.h> 18862214Sroger#include <dev/pci/bktr/bktr_os.h> 18962214Sroger#else /* Traditional location for .h files */ 19062214Sroger#include <machine/ioctl_meteor.h> 19162214Sroger#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 19262214Sroger#include <dev/bktr/bktr_reg.h> 19362214Sroger#include <dev/bktr/bktr_tuner.h> 19462214Sroger#include <dev/bktr/bktr_card.h> 19562214Sroger#include <dev/bktr/bktr_audio.h> 19662214Sroger#include <dev/bktr/bktr_core.h> 19762214Sroger#include <dev/bktr/bktr_os.h> 19862214Sroger#endif 19951694Sroger 20062214Sroger 20162214Sroger 20251694Sroger/****************************/ 20351694Sroger/* *** FreeBSD 4.x code *** */ 20451694Sroger/****************************/ 20551694Sroger#if (__FreeBSD_version >= 400000) 20651694Sroger 20751694Srogerstatic int bktr_probe( device_t dev ); 20851694Srogerstatic int bktr_attach( device_t dev ); 20951694Srogerstatic int bktr_detach( device_t dev ); 21051694Srogerstatic int bktr_shutdown( device_t dev ); 21151694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21251694Sroger 21351694Srogerstatic device_method_t bktr_methods[] = { 21451694Sroger /* Device interface */ 21551694Sroger DEVMETHOD(device_probe, bktr_probe), 21651694Sroger DEVMETHOD(device_attach, bktr_attach), 21751694Sroger DEVMETHOD(device_detach, bktr_detach), 21851694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 21951694Sroger 22051694Sroger { 0, 0 } 22151694Sroger}; 22251694Sroger 22351694Srogerstatic driver_t bktr_driver = { 22451694Sroger "bktr", 22551694Sroger bktr_methods, 22651694Sroger sizeof(struct bktr_softc), 22751694Sroger}; 22851694Sroger 22951694Srogerstatic devclass_t bktr_devclass; 23051694Sroger 23151694Srogerstatic d_open_t bktr_open; 23251694Srogerstatic d_close_t bktr_close; 23351694Srogerstatic d_read_t bktr_read; 23451694Srogerstatic d_write_t bktr_write; 23551694Srogerstatic d_ioctl_t bktr_ioctl; 23651694Srogerstatic d_mmap_t bktr_mmap; 23751694Srogerstatic d_poll_t bktr_poll; 23851694Sroger 23951694Sroger#define CDEV_MAJOR 92 24051694Srogerstatic struct cdevsw bktr_cdevsw = { 24151694Sroger /* open */ bktr_open, 24251694Sroger /* close */ bktr_close, 24351694Sroger /* read */ bktr_read, 24451694Sroger /* write */ bktr_write, 24551694Sroger /* ioctl */ bktr_ioctl, 24651694Sroger /* poll */ bktr_poll, 24751694Sroger /* mmap */ bktr_mmap, 24851694Sroger /* strategy */ nostrategy, 24951694Sroger /* name */ "bktr", 25051694Sroger /* maj */ CDEV_MAJOR, 25151694Sroger /* dump */ nodump, 25251694Sroger /* psize */ nopsize, 25351694Sroger /* flags */ 0, 25451694Sroger /* bmaj */ -1 25551694Sroger}; 25651694Sroger 25752995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 25851694Sroger 25951694Sroger 26051694Sroger/* 26151694Sroger * the boot time probe routine. 26251694Sroger */ 26351694Srogerstatic int 26451694Srogerbktr_probe( device_t dev ) 26551694Sroger{ 26651694Sroger unsigned int type = pci_get_devid(dev); 26751694Sroger unsigned int rev = pci_get_revid(dev); 26851694Sroger 26951694Sroger switch (type) { 27051694Sroger case BROOKTREE_848_PCI_ID: 27151694Sroger if (rev == 0x12) device_set_desc(dev, "BrookTree 848A"); 27251694Sroger else device_set_desc(dev, "BrookTree 848"); 27351694Sroger return 0; 27451694Sroger case BROOKTREE_849_PCI_ID: 27551694Sroger device_set_desc(dev, "BrookTree 849A"); 27651694Sroger return 0; 27751694Sroger case BROOKTREE_878_PCI_ID: 27851694Sroger device_set_desc(dev, "BrookTree 878"); 27951694Sroger return 0; 28051694Sroger case BROOKTREE_879_PCI_ID: 28151694Sroger device_set_desc(dev, "BrookTree 879"); 28251694Sroger return 0; 28351694Sroger }; 28451694Sroger 28551694Sroger return ENXIO; 28651694Sroger} 28751694Sroger 28851694Sroger 28951694Sroger/* 29051694Sroger * the attach routine. 29151694Sroger */ 29251694Srogerstatic int 29351694Srogerbktr_attach( device_t dev ) 29451694Sroger{ 29551694Sroger u_long latency; 29651694Sroger u_long fun; 29751694Sroger u_long val; 29851694Sroger unsigned int rev; 29951694Sroger unsigned int unit; 30051694Sroger int error = 0; 30151694Sroger int rid; 30251694Sroger#ifdef BROOKTREE_IRQ 30351694Sroger u_long old_irq, new_irq; 30451694Sroger#endif 30551694Sroger 30651694Sroger struct bktr_softc *bktr = device_get_softc(dev); 30751694Sroger 30851694Sroger unit = device_get_unit(dev); 30951694Sroger 31062112Sroger /* build the device name for bktr_name() */ 31162112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 31262112Sroger 31351694Sroger /* 31451694Sroger * Enable bus mastering and Memory Mapped device 31551694Sroger */ 31651694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 31751694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 31851694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 31951694Sroger 32051694Sroger /* 32151694Sroger * Map control/status registers. 32251694Sroger */ 32361035Speter rid = PCIR_MAPS; 32451694Sroger bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 32551694Sroger 0, ~0, 1, RF_ACTIVE); 32651694Sroger 32751694Sroger if (!bktr->res_mem) { 32851694Sroger device_printf(dev, "could not map memory\n"); 32951694Sroger error = ENXIO; 33051694Sroger goto fail; 33151694Sroger } 33259014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 33359014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 33451694Sroger 33559014Sroger 33651694Sroger /* 33751694Sroger * Disable the brooktree device 33851694Sroger */ 33959014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 34059014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 34151694Sroger 34251694Sroger 34351694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 34451694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 34551694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 34651694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 34751694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 34851694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 34951694Sroger#endif 35051694Sroger 35151694Sroger /* 35251694Sroger * Allocate our interrupt. 35351694Sroger */ 35451694Sroger rid = 0; 35551694Sroger bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 35651694Sroger RF_SHAREABLE | RF_ACTIVE); 35751694Sroger if (bktr->res_irq == NULL) { 35851694Sroger device_printf(dev, "could not map interrupt\n"); 35951694Sroger error = ENXIO; 36051694Sroger goto fail; 36151694Sroger } 36251694Sroger 36359250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 36451694Sroger bktr_intr, bktr, &bktr->res_ih); 36551694Sroger if (error) { 36651694Sroger device_printf(dev, "could not setup irq\n"); 36751694Sroger goto fail; 36851694Sroger 36951694Sroger } 37051694Sroger 37151694Sroger 37251694Sroger /* Update the Device Control Register */ 37351694Sroger /* on Bt878 and Bt879 cards */ 37451694Sroger fun = pci_read_config( dev, 0x40, 2); 37551694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 37651694Sroger 37751694Sroger#if defined( BKTR_430_FX_MODE ) 37851694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 37951694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 38051694Sroger#endif 38151694Sroger 38251694Sroger#if defined( BKTR_SIS_VIA_MODE ) 38351694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 38451694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 38551694Sroger OPTi chipset motherboards too */ 38651694Sroger#endif 38751694Sroger pci_write_config(dev, 0x40, fun, 2); 38851694Sroger 38951694Sroger 39051694Sroger /* XXX call bt848_i2c dependent attach() routine */ 39151694Sroger#if (NSMBUS > 0) 39259014Sroger if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc)) 39351694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 39451694Sroger#endif 39551694Sroger 39651694Sroger 39751694Sroger/* 39851694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 39951694Sroger * you have more than four, then 16 would probably be a better value. 40051694Sroger */ 40151694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 40251694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 40351694Sroger#endif 40451694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 40551694Sroger latency = (latency >> 8) & 0xff; 40651694Sroger if ( bootverbose ) { 40751694Sroger if (latency) 40851694Sroger printf("brooktree%d: PCI bus latency is", unit); 40951694Sroger else 41051694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 41151694Sroger unit); 41251694Sroger } 41351694Sroger if ( !latency ) { 41451694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 41551694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 41651694Sroger } 41751694Sroger if ( bootverbose ) { 41851694Sroger printf(" %d.\n", (int) latency); 41951694Sroger } 42051694Sroger 42151694Sroger /* read the pci device id and revision id */ 42251694Sroger fun = pci_get_devid(dev); 42351694Sroger rev = pci_get_revid(dev); 42451694Sroger 42551694Sroger /* call the common attach code */ 42651694Sroger common_bktr_attach( bktr, unit, fun, rev ); 42751694Sroger 42851694Sroger make_dev(&bktr_cdevsw, unit, 0, 0, 0444, "bktr%d", unit); 42951694Sroger make_dev(&bktr_cdevsw, unit+16, 0, 0, 0444, "tuner%d", unit); 43051694Sroger make_dev(&bktr_cdevsw, unit+32, 0, 0, 0444, "vbi%d", unit); 43151694Sroger 43251694Sroger return 0; 43351694Sroger 43451694Srogerfail: 43551694Sroger return error; 43651694Sroger 43751694Sroger} 43851694Sroger 43951694Sroger/* 44051694Sroger * the detach routine. 44151694Sroger */ 44251694Srogerstatic int 44351694Srogerbktr_detach( device_t dev ) 44451694Sroger{ 44551694Sroger struct bktr_softc *bktr = device_get_softc(dev); 44651694Sroger 44751694Sroger /* Disable the brooktree device */ 44859014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 44959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 45051694Sroger 45151694Sroger /* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */ 45251694Sroger 45351694Sroger /* 45451694Sroger * Deallocate resources. 45551694Sroger */ 45651694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 45751694Sroger bus_release_resource(dev, SYS_RES_IRQ, 0, bktr->res_irq); 45861035Speter bus_release_resource(dev, SYS_RES_MEMORY, PCIR_MAPS, bktr->res_mem); 45951694Sroger 46051694Sroger return 0; 46151694Sroger} 46251694Sroger 46351694Sroger/* 46451694Sroger * the shutdown routine. 46551694Sroger */ 46651694Srogerstatic int 46751694Srogerbktr_shutdown( device_t dev ) 46851694Sroger{ 46951694Sroger struct bktr_softc *bktr = device_get_softc(dev); 47051694Sroger 47151694Sroger /* Disable the brooktree device */ 47259014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 47359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 47451694Sroger 47551694Sroger return 0; 47651694Sroger} 47751694Sroger 47851694Sroger 47951694Sroger/* 48051694Sroger * Special Memory Allocation 48151694Sroger */ 48251694Srogervm_offset_t 48351694Srogerget_bktr_mem( int unit, unsigned size ) 48451694Sroger{ 48551694Sroger vm_offset_t addr = 0; 48651694Sroger 48751694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 48851694Sroger if (addr == 0) 48951694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 49051694Sroger if (addr == 0) { 49151694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 49251694Sroger unit, size); 49351694Sroger } 49451694Sroger 49551694Sroger return( addr ); 49651694Sroger} 49751694Sroger 49851694Sroger 49951694Sroger/*--------------------------------------------------------- 50051694Sroger** 50151694Sroger** BrookTree 848 character device driver routines 50251694Sroger** 50351694Sroger**--------------------------------------------------------- 50451694Sroger*/ 50551694Sroger 50651694Sroger#define VIDEO_DEV 0x00 50751694Sroger#define TUNER_DEV 0x01 50851694Sroger#define VBI_DEV 0x02 50951694Sroger 51051694Sroger#define UNIT(x) ((x) & 0x0f) 51151694Sroger#define FUNCTION(x) (x >> 4) 51251694Sroger 51351694Sroger/* 51451694Sroger * 51551694Sroger */ 51651694Srogerint 51751694Srogerbktr_open( dev_t dev, int flags, int fmt, struct proc *p ) 51851694Sroger{ 51951694Sroger bktr_ptr_t bktr; 52051694Sroger int unit; 52151694Sroger int result; 52251694Sroger 52351694Sroger unit = UNIT( minor(dev) ); 52451694Sroger 52551694Sroger /* Get the device data */ 52651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 52751694Sroger if (bktr == NULL) { 52851694Sroger /* the device is no longer valid/functioning */ 52951694Sroger return (ENXIO); 53051694Sroger } 53151694Sroger 53251694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 53351694Sroger return( ENXIO ); 53451694Sroger 53551694Sroger /* Record that the device is now busy */ 53651694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 53751694Sroger 53851694Sroger 53951694Sroger if (bt848_card != -1) { 54051694Sroger if ((bt848_card >> 8 == unit ) && 54151694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 54251694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 54351694Sroger bktr->bt848_card = (bt848_card & 0xff); 54451694Sroger probeCard(bktr, FALSE, unit); 54551694Sroger } 54651694Sroger } 54751694Sroger } 54851694Sroger 54951694Sroger if (bt848_tuner != -1) { 55051694Sroger if ((bt848_tuner >> 8 == unit ) && 55151694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 55251694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 55351694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 55451694Sroger probeCard(bktr, FALSE, unit); 55551694Sroger } 55651694Sroger } 55751694Sroger } 55851694Sroger 55951694Sroger if (bt848_reverse_mute != -1) { 56059014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 56151694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 56251694Sroger } 56351694Sroger } 56451694Sroger 56559014Sroger if (bt848_slow_msp_audio != -1) { 56659014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 56759014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 56859014Sroger } 56959014Sroger } 57059014Sroger 57151694Sroger switch ( FUNCTION( minor(dev) ) ) { 57251694Sroger case VIDEO_DEV: 57351694Sroger result = video_open( bktr ); 57451694Sroger break; 57551694Sroger case TUNER_DEV: 57651694Sroger result = tuner_open( bktr ); 57751694Sroger break; 57851694Sroger case VBI_DEV: 57951694Sroger result = vbi_open( bktr ); 58051694Sroger break; 58151694Sroger default: 58251694Sroger result = ENXIO; 58351694Sroger break; 58451694Sroger } 58551694Sroger 58651694Sroger /* If there was an error opening the device, undo the busy status */ 58751694Sroger if (result != 0) 58851694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 58951694Sroger return( result ); 59051694Sroger} 59151694Sroger 59251694Sroger 59351694Sroger/* 59451694Sroger * 59551694Sroger */ 59651694Srogerint 59751694Srogerbktr_close( dev_t dev, int flags, int fmt, struct proc *p ) 59851694Sroger{ 59951694Sroger bktr_ptr_t bktr; 60051694Sroger int unit; 60151694Sroger int result; 60251694Sroger 60351694Sroger unit = UNIT( minor(dev) ); 60451694Sroger 60551694Sroger /* Get the device data */ 60651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 60751694Sroger if (bktr == NULL) { 60851694Sroger /* the device is no longer valid/functioning */ 60951694Sroger return (ENXIO); 61051694Sroger } 61151694Sroger 61251694Sroger switch ( FUNCTION( minor(dev) ) ) { 61351694Sroger case VIDEO_DEV: 61451694Sroger result = video_close( bktr ); 61551694Sroger break; 61651694Sroger case TUNER_DEV: 61751694Sroger result = tuner_close( bktr ); 61851694Sroger break; 61951694Sroger case VBI_DEV: 62051694Sroger result = vbi_close( bktr ); 62151694Sroger break; 62251694Sroger default: 62351694Sroger return (ENXIO); 62451694Sroger break; 62551694Sroger } 62651694Sroger 62751694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 62851694Sroger return( result ); 62951694Sroger} 63051694Sroger 63151694Sroger 63251694Sroger/* 63351694Sroger * 63451694Sroger */ 63551694Srogerint 63651694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 63751694Sroger{ 63851694Sroger bktr_ptr_t bktr; 63951694Sroger int unit; 64051694Sroger 64151694Sroger unit = UNIT(minor(dev)); 64251694Sroger 64351694Sroger /* Get the device data */ 64451694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 64551694Sroger if (bktr == NULL) { 64651694Sroger /* the device is no longer valid/functioning */ 64751694Sroger return (ENXIO); 64851694Sroger } 64951694Sroger 65051694Sroger switch ( FUNCTION( minor(dev) ) ) { 65151694Sroger case VIDEO_DEV: 65251694Sroger return( video_read( bktr, unit, dev, uio ) ); 65351694Sroger case VBI_DEV: 65451694Sroger return( vbi_read( bktr, uio, ioflag ) ); 65551694Sroger } 65651694Sroger return( ENXIO ); 65751694Sroger} 65851694Sroger 65951694Sroger 66051694Sroger/* 66151694Sroger * 66251694Sroger */ 66351694Srogerint 66451694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 66551694Sroger{ 66651694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 66751694Sroger} 66851694Sroger 66951694Sroger 67051694Sroger/* 67151694Sroger * 67251694Sroger */ 67351694Srogerint 67451694Srogerbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) 67551694Sroger{ 67651694Sroger bktr_ptr_t bktr; 67751694Sroger int unit; 67851694Sroger 67951694Sroger unit = UNIT(minor(dev)); 68051694Sroger 68151694Sroger /* Get the device data */ 68251694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 68351694Sroger if (bktr == NULL) { 68451694Sroger /* the device is no longer valid/functioning */ 68551694Sroger return (ENXIO); 68651694Sroger } 68751694Sroger 68851694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 68951694Sroger return( ENOMEM ); 69051694Sroger 69151694Sroger switch ( FUNCTION( minor(dev) ) ) { 69251694Sroger case VIDEO_DEV: 69351694Sroger return( video_ioctl( bktr, unit, cmd, arg, pr ) ); 69451694Sroger case TUNER_DEV: 69551694Sroger return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); 69651694Sroger } 69751694Sroger 69851694Sroger return( ENXIO ); 69951694Sroger} 70051694Sroger 70151694Sroger 70251694Sroger/* 70351694Sroger * 70451694Sroger */ 70551694Srogerint 70651694Srogerbktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 70751694Sroger{ 70851694Sroger int unit; 70951694Sroger bktr_ptr_t bktr; 71051694Sroger 71151694Sroger unit = UNIT(minor(dev)); 71251694Sroger 71351694Sroger if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 71451694Sroger return( -1 ); 71551694Sroger 71651694Sroger /* Get the device data */ 71751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 71851694Sroger if (bktr == NULL) { 71951694Sroger /* the device is no longer valid/functioning */ 72051694Sroger return (ENXIO); 72151694Sroger } 72251694Sroger 72351694Sroger if (nprot & PROT_EXEC) 72451694Sroger return( -1 ); 72551694Sroger 72651694Sroger if (offset < 0) 72751694Sroger return( -1 ); 72851694Sroger 72951694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 73051694Sroger return( -1 ); 73151694Sroger 73259250Sroger return( atop(vtophys(bktr->bigbuf) + offset) ); 73351694Sroger} 73451694Sroger 73551694Srogerint bktr_poll( dev_t dev, int events, struct proc *p) 73651694Sroger{ 73751694Sroger int unit; 73851694Sroger bktr_ptr_t bktr; 73951694Sroger int revents = 0; 74059277Sroger DECLARE_INTR_MASK(s); 74151694Sroger 74251694Sroger unit = UNIT(minor(dev)); 74351694Sroger 74451694Sroger /* Get the device data */ 74551694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 74651694Sroger if (bktr == NULL) { 74751694Sroger /* the device is no longer valid/functioning */ 74851694Sroger return (ENXIO); 74951694Sroger } 75051694Sroger 75159277Sroger DISABLE_INTR(s); 75251694Sroger 75351694Sroger if (events & (POLLIN | POLLRDNORM)) { 75451694Sroger 75551694Sroger switch ( FUNCTION( minor(dev) ) ) { 75651694Sroger case VBI_DEV: 75751694Sroger if(bktr->vbisize == 0) 75851694Sroger selrecord(p, &bktr->vbi_select); 75951694Sroger else 76051694Sroger revents |= events & (POLLIN | POLLRDNORM); 76151694Sroger break; 76251694Sroger } 76351694Sroger } 76451694Sroger 76559250Sroger ENABLE_INTR(s); 76651694Sroger 76751694Sroger return (revents); 76851694Sroger} 76951694Sroger 77051694Sroger#endif /* FreeBSD 4.x specific kernel interface routines */ 77151694Sroger 77251694Sroger/**********************************/ 77351694Sroger/* *** FreeBSD 2.2.x and 3.x *** */ 77451694Sroger/**********************************/ 77551694Sroger 77651694Sroger#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3)) 77751694Sroger 77851694Srogerstatic bktr_reg_t brooktree[ NBKTR ]; 77951694Sroger 78051694Srogerstatic const char* bktr_probe( pcici_t tag, pcidi_t type ); 78151694Srogerstatic void bktr_attach( pcici_t tag, int unit ); 78251694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 78351694Sroger 78451694Srogerstatic u_long bktr_count; 78551694Sroger 78651694Srogerstatic struct pci_device bktr_device = { 78751694Sroger "bktr", 78851694Sroger bktr_probe, 78951694Sroger bktr_attach, 79051694Sroger &bktr_count 79151694Sroger}; 79251694Sroger 79351694SrogerDATA_SET (pcidevice_set, bktr_device); 79451694Sroger 79551694Srogerstatic d_open_t bktr_open; 79651694Srogerstatic d_close_t bktr_close; 79751694Srogerstatic d_read_t bktr_read; 79851694Srogerstatic d_write_t bktr_write; 79951694Srogerstatic d_ioctl_t bktr_ioctl; 80051694Srogerstatic d_mmap_t bktr_mmap; 80151694Srogerstatic d_poll_t bktr_poll; 80251694Sroger 80351694Sroger#define CDEV_MAJOR 92 80451694Srogerstatic struct cdevsw bktr_cdevsw = 80551694Sroger{ 80651694Sroger bktr_open, bktr_close, bktr_read, bktr_write, 80751694Sroger bktr_ioctl, nostop, nullreset, nodevtotty, 80851694Sroger bktr_poll, bktr_mmap, NULL, "bktr", 80951694Sroger NULL, -1 81051694Sroger}; 81151694Sroger 81251694Srogerstatic int bktr_devsw_installed; 81351694Sroger 81451694Srogerstatic void 81551694Srogerbktr_drvinit( void *unused ) 81651694Sroger{ 81751694Sroger dev_t dev; 81851694Sroger 81951694Sroger if ( ! bktr_devsw_installed ) { 82051694Sroger dev = makedev(CDEV_MAJOR, 0); 82151694Sroger cdevsw_add(&dev,&bktr_cdevsw, NULL); 82251694Sroger bktr_devsw_installed = 1; 82351694Sroger } 82451694Sroger} 82551694Sroger 82651694SrogerSYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL) 82751694Sroger 82851694Sroger/* 82951694Sroger * the boot time probe routine. 83051694Sroger */ 83151694Srogerstatic const char* 83251694Srogerbktr_probe( pcici_t tag, pcidi_t type ) 83351694Sroger{ 83451694Sroger unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff; 83551694Sroger 83651694Sroger switch (type) { 83751694Sroger case BROOKTREE_848_PCI_ID: 83851694Sroger if (rev == 0x12) return("BrookTree 848A"); 83951694Sroger else return("BrookTree 848"); 84051694Sroger case BROOKTREE_849_PCI_ID: 84151694Sroger return("BrookTree 849A"); 84251694Sroger case BROOKTREE_878_PCI_ID: 84351694Sroger return("BrookTree 878"); 84451694Sroger case BROOKTREE_879_PCI_ID: 84551694Sroger return("BrookTree 879"); 84651694Sroger }; 84751694Sroger 84851694Sroger return ((char *)0); 84951694Sroger} 85051694Sroger 85151694Sroger/* 85251694Sroger * the attach routine. 85351694Sroger */ 85451694Srogerstatic void 85551694Srogerbktr_attach( pcici_t tag, int unit ) 85651694Sroger{ 85751694Sroger bktr_ptr_t bktr; 85851694Sroger u_long latency; 85951694Sroger u_long fun; 86051694Sroger unsigned int rev; 86159014Sroger unsigned long base; 86251694Sroger#ifdef BROOKTREE_IRQ 86351694Sroger u_long old_irq, new_irq; 86451694Sroger#endif 86551694Sroger 86651694Sroger bktr = &brooktree[unit]; 86751694Sroger 86851694Sroger if (unit >= NBKTR) { 86951694Sroger printf("brooktree%d: attach: only %d units configured.\n", 87051694Sroger unit, NBKTR); 87151694Sroger printf("brooktree%d: attach: invalid unit number.\n", unit); 87251694Sroger return; 87351694Sroger } 87451694Sroger 87562112Sroger /* build the device name for bktr_name() */ 87662112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 87762112Sroger 87851694Sroger /* Enable Memory Mapping */ 87951694Sroger fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 88051694Sroger pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2); 88151694Sroger 88251694Sroger /* Enable Bus Mastering */ 88351694Sroger fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 88451694Sroger pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4); 88551694Sroger 88651694Sroger bktr->tag = tag; 88751694Sroger 88851694Sroger 88951694Sroger /* 89051694Sroger * Map control/status registers 89151694Sroger */ 89259014Sroger pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base, 89351694Sroger &bktr->phys_base ); 89459014Sroger#if (__FreeBSD_version >= 300000) 89559014Sroger bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */ 89659014Sroger bktr->memh = (bus_space_handle_t)base; /* XXX functions here */ 89759014Sroger#endif 89851694Sroger 89951694Sroger /* 90051694Sroger * Disable the brooktree device 90151694Sroger */ 90259014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 90359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 90451694Sroger 90551694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 90651694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 90751694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 90851694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 90951694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 91051694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 91151694Sroger#endif 91251694Sroger 91351694Sroger /* 91451694Sroger * setup the interrupt handling routine 91551694Sroger */ 91659250Sroger pci_map_int(tag, bktr_intr, (void*) bktr, &tty_imask); 91751694Sroger 91851694Sroger 91951694Sroger /* Update the Device Control Register */ 92051694Sroger /* on Bt878 and Bt879 cards */ 92151694Sroger fun = pci_conf_read(tag, 0x40); 92251694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 92351694Sroger 92451694Sroger#if defined( BKTR_430_FX_MODE ) 92551694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 92651694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 92751694Sroger#endif 92851694Sroger 92951694Sroger#if defined( BKTR_SIS_VIA_MODE ) 93051694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 93151694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 93251694Sroger OPTi chipset motherboards too */ 93351694Sroger#endif 93451694Sroger pci_conf_write(tag, 0x40, fun); 93551694Sroger 93651694Sroger 93751694Sroger /* XXX call bt848_i2c dependent attach() routine */ 93851694Sroger#if (NSMBUS > 0) 93959014Sroger if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc)) 94051694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 94151694Sroger#endif 94251694Sroger 94351694Sroger 94451694Sroger/* 94551694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 94651694Sroger * you have more than four, then 16 would probably be a better value. 94751694Sroger */ 94851694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 94951694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 95051694Sroger#endif 95151694Sroger latency = pci_conf_read(tag, PCI_LATENCY_TIMER); 95251694Sroger latency = (latency >> 8) & 0xff; 95351694Sroger if ( bootverbose ) { 95451694Sroger if (latency) 95551694Sroger printf("brooktree%d: PCI bus latency is", unit); 95651694Sroger else 95751694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 95851694Sroger unit); 95951694Sroger } 96051694Sroger if ( !latency ) { 96151694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 96251694Sroger pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); 96351694Sroger } 96451694Sroger if ( bootverbose ) { 96551694Sroger printf(" %d.\n", (int) latency); 96651694Sroger } 96751694Sroger 96851694Sroger 96951694Sroger /* read the pci device id and revision id */ 97051694Sroger fun = pci_conf_read(tag, PCI_ID_REG); 97151694Sroger rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff; 97251694Sroger 97351694Sroger /* call the common attach code */ 97451694Sroger common_bktr_attach( bktr, unit, fun, rev ); 97551694Sroger 97651694Sroger#ifdef DEVFS 97751694Sroger /* XXX This just throw away the token, which should probably be fixed when 97851694Sroger DEVFS is finally made really operational. */ 97951694Sroger devfs_add_devswf(&bktr_cdevsw, unit, DV_CHR, 0, 0, 0444, "bktr%d", unit); 98051694Sroger devfs_add_devswf(&bktr_cdevsw, unit+16, DV_CHR, 0, 0, 0444, "tuner%d", unit); 98151694Sroger devfs_add_devswf(&bktr_cdevsw, unit+32, DV_CHR, 0, 0, 0444, "vbi%d", unit); 98251694Sroger#endif /* DEVFS */ 98351694Sroger 98451694Sroger} 98551694Sroger 98651694Sroger 98751694Sroger/* 98851694Sroger * Special Memory Allocation 98951694Sroger */ 99051694Srogervm_offset_t 99151694Srogerget_bktr_mem( int unit, unsigned size ) 99251694Sroger{ 99351694Sroger vm_offset_t addr = 0; 99451694Sroger 99551694Sroger addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24); 99651694Sroger if (addr == 0) 99751694Sroger addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 99851694Sroger PAGE_SIZE); 99951694Sroger if (addr == 0) { 100051694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 100151694Sroger unit, size); 100251694Sroger } 100351694Sroger 100451694Sroger return( addr ); 100551694Sroger} 100651694Sroger 100751694Sroger/*--------------------------------------------------------- 100851694Sroger** 100951694Sroger** BrookTree 848 character device driver routines 101051694Sroger** 101151694Sroger**--------------------------------------------------------- 101251694Sroger*/ 101351694Sroger 101451694Sroger 101551694Sroger#define VIDEO_DEV 0x00 101651694Sroger#define TUNER_DEV 0x01 101751694Sroger#define VBI_DEV 0x02 101851694Sroger 101951694Sroger#define UNIT(x) ((x) & 0x0f) 102051694Sroger#define FUNCTION(x) ((x >> 4) & 0x0f) 102151694Sroger 102251694Sroger 102351694Sroger/* 102451694Sroger * 102551694Sroger */ 102651694Srogerint 102751694Srogerbktr_open( dev_t dev, int flags, int fmt, struct proc *p ) 102851694Sroger{ 102951694Sroger bktr_ptr_t bktr; 103051694Sroger int unit; 103151694Sroger 103251694Sroger unit = UNIT( minor(dev) ); 103351694Sroger if (unit >= NBKTR) /* unit out of range */ 103451694Sroger return( ENXIO ); 103551694Sroger 103651694Sroger bktr = &(brooktree[ unit ]); 103751694Sroger 103851694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 103951694Sroger return( ENXIO ); 104051694Sroger 104151694Sroger 104251694Sroger if (bt848_card != -1) { 104351694Sroger if ((bt848_card >> 8 == unit ) && 104451694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 104551694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 104651694Sroger bktr->bt848_card = (bt848_card & 0xff); 104751694Sroger probeCard(bktr, FALSE, unit); 104851694Sroger } 104951694Sroger } 105051694Sroger } 105151694Sroger 105251694Sroger if (bt848_tuner != -1) { 105351694Sroger if ((bt848_tuner >> 8 == unit ) && 105451694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 105551694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 105651694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 105751694Sroger probeCard(bktr, FALSE, unit); 105851694Sroger } 105951694Sroger } 106051694Sroger } 106151694Sroger 106251694Sroger if (bt848_reverse_mute != -1) { 106359014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 106451694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 106551694Sroger } 106651694Sroger } 106751694Sroger 106859014Sroger if (bt848_slow_msp_audio != -1) { 106959014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 107059014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 107159014Sroger } 107259014Sroger } 107351694Sroger 107451694Sroger switch ( FUNCTION( minor(dev) ) ) { 107551694Sroger case VIDEO_DEV: 107651694Sroger return( video_open( bktr ) ); 107751694Sroger case TUNER_DEV: 107851694Sroger return( tuner_open( bktr ) ); 107951694Sroger case VBI_DEV: 108051694Sroger return( vbi_open( bktr ) ); 108151694Sroger } 108251694Sroger return( ENXIO ); 108351694Sroger} 108451694Sroger 108551694Sroger 108651694Sroger/* 108751694Sroger * 108851694Sroger */ 108951694Srogerint 109051694Srogerbktr_close( dev_t dev, int flags, int fmt, struct proc *p ) 109151694Sroger{ 109251694Sroger bktr_ptr_t bktr; 109351694Sroger int unit; 109451694Sroger 109551694Sroger unit = UNIT( minor(dev) ); 109651694Sroger if (unit >= NBKTR) /* unit out of range */ 109751694Sroger return( ENXIO ); 109851694Sroger 109951694Sroger bktr = &(brooktree[ unit ]); 110051694Sroger 110151694Sroger switch ( FUNCTION( minor(dev) ) ) { 110251694Sroger case VIDEO_DEV: 110351694Sroger return( video_close( bktr ) ); 110451694Sroger case TUNER_DEV: 110551694Sroger return( tuner_close( bktr ) ); 110651694Sroger case VBI_DEV: 110751694Sroger return( vbi_close( bktr ) ); 110851694Sroger } 110951694Sroger 111051694Sroger return( ENXIO ); 111151694Sroger} 111251694Sroger 111351694Sroger/* 111451694Sroger * 111551694Sroger */ 111651694Srogerint 111751694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 111851694Sroger{ 111951694Sroger bktr_ptr_t bktr; 112051694Sroger int unit; 112151694Sroger 112251694Sroger unit = UNIT(minor(dev)); 112351694Sroger if (unit >= NBKTR) /* unit out of range */ 112451694Sroger return( ENXIO ); 112551694Sroger 112651694Sroger bktr = &(brooktree[unit]); 112751694Sroger 112851694Sroger switch ( FUNCTION( minor(dev) ) ) { 112951694Sroger case VIDEO_DEV: 113051694Sroger return( video_read( bktr, unit, dev, uio ) ); 113151694Sroger case VBI_DEV: 113251694Sroger return( vbi_read( bktr, uio, ioflag ) ); 113351694Sroger } 113451694Sroger return( ENXIO ); 113551694Sroger} 113651694Sroger 113751694Sroger 113851694Sroger/* 113951694Sroger * 114051694Sroger */ 114151694Srogerint 114251694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 114351694Sroger{ 114451694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 114551694Sroger} 114651694Sroger 114751694Sroger/* 114851694Sroger * 114951694Sroger */ 115051694Srogerint 115151694Srogerbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) 115251694Sroger{ 115351694Sroger bktr_ptr_t bktr; 115451694Sroger int unit; 115551694Sroger 115651694Sroger unit = UNIT(minor(dev)); 115751694Sroger if (unit >= NBKTR) /* unit out of range */ 115851694Sroger return( ENXIO ); 115951694Sroger 116051694Sroger bktr = &(brooktree[ unit ]); 116151694Sroger 116251694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 116351694Sroger return( ENOMEM ); 116451694Sroger 116551694Sroger switch ( FUNCTION( minor(dev) ) ) { 116651694Sroger case VIDEO_DEV: 116751694Sroger return( video_ioctl( bktr, unit, cmd, arg, pr ) ); 116851694Sroger case TUNER_DEV: 116951694Sroger return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); 117051694Sroger } 117151694Sroger 117251694Sroger return( ENXIO ); 117351694Sroger} 117451694Sroger 117551694Sroger/* 117651694Sroger * bktr_mmap. 117751694Sroger * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually 117852593Sroger * edit the line below and change "vm_offset_t" to "int" 117951694Sroger */ 118051694Srogerint bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 118151694Sroger 118251694Sroger{ 118351694Sroger int unit; 118451694Sroger bktr_ptr_t bktr; 118551694Sroger 118651694Sroger unit = UNIT(minor(dev)); 118751694Sroger 118851694Sroger if (unit >= NBKTR || FUNCTION(minor(dev)) > 0) 118951694Sroger return( -1 ); 119051694Sroger 119151694Sroger bktr = &(brooktree[ unit ]); 119251694Sroger 119351694Sroger if (nprot & PROT_EXEC) 119451694Sroger return( -1 ); 119551694Sroger 119651694Sroger if (offset < 0) 119751694Sroger return( -1 ); 119851694Sroger 119951694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 120051694Sroger return( -1 ); 120151694Sroger 120251694Sroger return( i386_btop(vtophys(bktr->bigbuf) + offset) ); 120351694Sroger} 120451694Sroger 120551694Srogerint bktr_poll( dev_t dev, int events, struct proc *p) 120651694Sroger{ 120751694Sroger int unit; 120851694Sroger bktr_ptr_t bktr; 120951694Sroger int revents = 0; 121051694Sroger 121151694Sroger unit = UNIT(minor(dev)); 121251694Sroger 121351694Sroger if (unit >= NBKTR) 121451694Sroger return( -1 ); 121551694Sroger 121651694Sroger bktr = &(brooktree[ unit ]); 121751694Sroger 121851694Sroger disable_intr(); 121951694Sroger 122051694Sroger if (events & (POLLIN | POLLRDNORM)) { 122151694Sroger 122251694Sroger switch ( FUNCTION( minor(dev) ) ) { 122351694Sroger case VBI_DEV: 122451694Sroger if(bktr->vbisize == 0) 122551694Sroger selrecord(p, &bktr->vbi_select); 122651694Sroger else 122751694Sroger revents |= events & (POLLIN | POLLRDNORM); 122851694Sroger break; 122951694Sroger } 123051694Sroger } 123151694Sroger 123251694Sroger enable_intr(); 123351694Sroger 123451694Sroger return (revents); 123551694Sroger} 123651694Sroger 123751694Sroger 123851694Sroger#endif /* FreeBSD 2.2.x and 3.x specific kernel interface routines */ 123951694Sroger 124051694Sroger 124151694Sroger/*****************/ 124251694Sroger/* *** BSDI *** */ 124351694Sroger/*****************/ 124451694Sroger 124551694Sroger#if defined(__bsdi__) 124651694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 124751694Sroger 124851694Sroger 124951694Sroger/*****************************/ 125051694Sroger/* *** OpenBSD / NetBSD *** */ 125151694Sroger/*****************************/ 125251694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 125359014Sroger 125459014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 125559014Sroger 125659014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 125759014Sroger 125859014Sroger#define bktr_open bktropen 125959014Sroger#define bktr_close bktrclose 126059014Sroger#define bktr_read bktrread 126159014Sroger#define bktr_write bktrwrite 126259014Sroger#define bktr_ioctl bktrioctl 126359014Sroger#define bktr_mmap bktrmmap 126459014Sroger 126559014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 126659014Sroger vm_offset_t, vm_offset_t); 126759014Sroger 126862112Sroger#if defined(__OpenBSD__) 126959014Srogerstatic int bktr_probe __P((struct device *, void *, void *)); 127059014Sroger#else 127159014Srogerstatic int bktr_probe __P((struct device *, struct cfdata *, void *)); 127259014Sroger#endif 127359014Srogerstatic void bktr_attach __P((struct device *, struct device *, void *)); 127459014Sroger 127559014Srogerstruct cfattach bktr_ca = { 127659014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 127759014Sroger}; 127859014Sroger 127959014Sroger#if defined(__NetBSD__) 128059014Srogerextern struct cfdriver bktr_cd; 128159014Sroger#else 128259014Srogerstruct cfdriver bktr_cd = { 128359014Sroger NULL, "bktr", DV_DULL 128459014Sroger}; 128559014Sroger#endif 128659014Sroger 128762112Srogerint 128862112Srogerbktr_probe(parent, match, aux) 128962112Sroger struct device *parent; 129062112Sroger#if defined(__OpenBSD__) 129159014Sroger void *match; 129259014Sroger#else 129359014Sroger struct cfdata *match; 129459014Sroger#endif 129559014Sroger void *aux; 129659014Sroger{ 129759014Sroger struct pci_attach_args *pa = aux; 129859014Sroger 129959014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 130059014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 130159014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 130259014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 130359014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 130459014Sroger return 1; 130559014Sroger 130659014Sroger return 0; 130759014Sroger} 130859014Sroger 130959014Sroger 131059014Sroger/* 131159014Sroger * the attach routine. 131259014Sroger */ 131359014Srogerstatic void 131462112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 131559014Sroger{ 131659014Sroger bktr_ptr_t bktr; 131759014Sroger u_long latency; 131859014Sroger u_long fun; 131959014Sroger unsigned int rev; 132059014Sroger 132159014Sroger#if defined(__OpenBSD__) 132259014Sroger struct pci_attach_args *pa = aux; 132359014Sroger pci_chipset_tag_t pc = pa->pa_pc; 132459014Sroger 132559014Sroger pci_intr_handle_t ih; 132659014Sroger const char *intrstr; 132759014Sroger int retval; 132859014Sroger int unit; 132959014Sroger 133059014Sroger bktr = (bktr_ptr_t)self; 133159014Sroger unit = bktr->bktr_dev.dv_unit; 133259014Sroger 133359014Sroger bktr->pc = pa->pa_pc; 133459014Sroger bktr->tag = pa->pa_tag; 133559014Sroger bktr->dmat = pa->pa_dmat; 133659014Sroger 133759014Sroger /* 133859014Sroger * map memory 133959014Sroger */ 134059014Sroger bktr->memt = pa->pa_memt; 134159014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 134259014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 134359014Sroger if (!retval) 134459014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 134559014Sroger bktr->obmemsz, 0, &bktr->memh); 134659014Sroger if (retval) { 134759014Sroger printf(": couldn't map memory\n"); 134859014Sroger return; 134959014Sroger } 135059014Sroger 135159014Sroger 135259014Sroger /* 135359014Sroger * map interrupt 135459014Sroger */ 135559014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 135659014Sroger pa->pa_intrline, &ih)) { 135759014Sroger printf(": couldn't map interrupt\n"); 135859014Sroger return; 135959014Sroger } 136059014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 136159014Sroger 136259014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 136359014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 136459014Sroger if (bktr->ih == NULL) { 136559014Sroger printf(": couldn't establish interrupt"); 136659014Sroger if (intrstr != NULL) 136759014Sroger printf(" at %s", intrstr); 136859014Sroger printf("\n"); 136959014Sroger return; 137059014Sroger } 137159014Sroger 137259014Sroger if (intrstr != NULL) 137359014Sroger printf(": %s\n", intrstr); 137459014Sroger#endif /* __OpenBSD__ */ 137559014Sroger 137659014Sroger#if defined(__NetBSD__) 137759014Sroger struct pci_attach_args *pa = aux; 137859014Sroger pci_intr_handle_t ih; 137959014Sroger const char *intrstr; 138059014Sroger int retval; 138159014Sroger int unit; 138259014Sroger 138359014Sroger bktr = (bktr_ptr_t)self; 138459014Sroger unit = bktr->bktr_dev.dv_unit; 138559014Sroger bktr->dmat = pa->pa_dmat; 138659014Sroger 138759014Sroger printf("\n"); 138859014Sroger 138959014Sroger /* 139059014Sroger * map memory 139159014Sroger */ 139259014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 139362112Sroger PCI_MAPREG_TYPE_MEM 139462112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 139562112Sroger &bktr->memt, &bktr->memh, NULL, 139662112Sroger &bktr->obmemsz); 139762112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 139862112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 139959014Sroger if (retval) { 140062112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 140159014Sroger return; 140259014Sroger } 140359014Sroger 140459014Sroger /* 140559014Sroger * Disable the brooktree device 140659014Sroger */ 140759014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 140859014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 140959014Sroger 141059014Sroger /* 141159014Sroger * map interrupt 141259014Sroger */ 141359014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 141459014Sroger pa->pa_intrline, &ih)) { 141562112Sroger printf("%s: couldn't map interrupt\n", 141662112Sroger bktr_name(bktr)); 141759014Sroger return; 141859014Sroger } 141959014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 142059014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 142159014Sroger bktr_intr, bktr); 142259014Sroger if (bktr->ih == NULL) { 142359014Sroger printf("%s: couldn't establish interrupt", 142462112Sroger bktr_name(bktr)); 142562112Sroger if (intrstr != NULL) 142662112Sroger printf(" at %s", intrstr); 142762112Sroger printf("\n"); 142862112Sroger return; 142959014Sroger } 143059014Sroger if (intrstr != NULL) 143162112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 143259014Sroger intrstr); 143359014Sroger#endif /* __NetBSD__ */ 143459014Sroger 143559014Sroger/* 143659014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 143759014Sroger * you have more than four, then 16 would probably be a better value. 143859014Sroger */ 143959014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 144059014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 144159014Sroger#endif 144259014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 144359014Sroger latency = (latency >> 8) & 0xff; 144459014Sroger 144562112Sroger if (!latency) { 144662112Sroger if (bootverbose) { 144759014Sroger printf("%s: PCI bus latency was 0 changing to %d", 144862112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 144959014Sroger } 145059014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 145159014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 145259014Sroger PCI_LATENCY_TIMER, latency<<8); 145359014Sroger } 145459014Sroger 145559014Sroger 145662112Sroger /* Enabled Bus Master 145762112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 145862112Sroger boot) */ 145959014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 146062112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 146162112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 146259014Sroger 146359014Sroger /* read the pci id and determine the card type */ 146459014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 146559014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 146659014Sroger 146762112Sroger common_bktr_attach(bktr, unit, fun, rev); 146859014Sroger} 146959014Sroger 147059014Sroger 147159014Sroger/* 147259014Sroger * Special Memory Allocation 147359014Sroger */ 147459014Srogervm_offset_t 147559014Srogerget_bktr_mem(bktr, dmapp, size) 147659014Sroger bktr_ptr_t bktr; 147759014Sroger bus_dmamap_t *dmapp; 147859014Sroger unsigned int size; 147959014Sroger{ 148059014Sroger bus_dma_tag_t dmat = bktr->dmat; 148159014Sroger bus_dma_segment_t seg; 148259014Sroger bus_size_t align; 148359014Sroger int rseg; 148459014Sroger caddr_t kva; 148559014Sroger 148659014Sroger /* 148759014Sroger * Allocate a DMA area 148859014Sroger */ 148959014Sroger align = 1 << 24; 149059014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 149159014Sroger &rseg, BUS_DMA_NOWAIT)) { 149259014Sroger align = PAGE_SIZE; 149359014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 149459014Sroger &rseg, BUS_DMA_NOWAIT)) { 149562112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 149662112Sroger bktr_name(bktr), size); 149759014Sroger return 0; 149859014Sroger } 149959014Sroger } 150059014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 150159014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 150262112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 150362112Sroger bktr_name(bktr), size); 150459014Sroger bus_dmamem_free(dmat, &seg, rseg); 150559014Sroger return 0; 150659014Sroger } 150759014Sroger#ifdef __OpenBSD__ 150859014Sroger bktr->dm_mapsize = size; 150959014Sroger#endif 151059014Sroger /* 151159014Sroger * Create and locd the DMA map for the DMA area 151259014Sroger */ 151359014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 151462112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 151562112Sroger bktr_name(bktr), size); 151659014Sroger bus_dmamem_unmap(dmat, kva, size); 151759014Sroger bus_dmamem_free(dmat, &seg, rseg); 151859014Sroger return 0; 151959014Sroger } 152059014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 152162112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 152262112Sroger bktr_name(bktr), size); 152359014Sroger bus_dmamem_unmap(dmat, kva, size); 152459014Sroger bus_dmamem_free(dmat, &seg, rseg); 152559014Sroger bus_dmamap_destroy(dmat, *dmapp); 152659014Sroger return 0; 152759014Sroger } 152859014Sroger return (vm_offset_t)kva; 152959014Sroger} 153059014Sroger 153159014Srogervoid 153259014Srogerfree_bktr_mem(bktr, dmap, kva) 153359014Sroger bktr_ptr_t bktr; 153459014Sroger bus_dmamap_t dmap; 153559014Sroger vm_offset_t kva; 153659014Sroger{ 153759014Sroger bus_dma_tag_t dmat = bktr->dmat; 153859014Sroger 153959014Sroger#ifdef __NetBSD__ 154059014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 154159014Sroger#else 154259014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 154359014Sroger#endif 154459014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 154559014Sroger bus_dmamap_destroy(dmat, dmap); 154659014Sroger} 154759014Sroger 154859014Sroger 154959014Sroger/*--------------------------------------------------------- 155059014Sroger** 155159014Sroger** BrookTree 848 character device driver routines 155259014Sroger** 155359014Sroger**--------------------------------------------------------- 155459014Sroger*/ 155559014Sroger 155659014Sroger 155759014Sroger#define VIDEO_DEV 0x00 155859014Sroger#define TUNER_DEV 0x01 155959014Sroger#define VBI_DEV 0x02 156059014Sroger 156162112Sroger#define UNIT(x) (minor((x) & 0x0f)) 156262112Sroger#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 156359014Sroger 156459014Sroger/* 156559014Sroger * 156659014Sroger */ 156759014Srogerint 156862112Srogerbktr_open(dev_t dev, int flags, int fmt, struct proc *p) 156959014Sroger{ 157059014Sroger bktr_ptr_t bktr; 157159014Sroger int unit; 157259014Sroger 157362112Sroger unit = UNIT(dev); 157459014Sroger 157559014Sroger /* unit out of range */ 157659014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 157762112Sroger return(ENXIO); 157859014Sroger 157959014Sroger bktr = bktr_cd.cd_devs[unit]; 158059014Sroger 158159014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 158262112Sroger return(ENXIO); 158359014Sroger 158462112Sroger switch (FUNCTION(dev)) { 158559014Sroger case VIDEO_DEV: 158662112Sroger return(video_open(bktr)); 158759014Sroger case TUNER_DEV: 158862112Sroger return(tuner_open(bktr)); 158959014Sroger case VBI_DEV: 159062112Sroger return(vbi_open(bktr)); 159159014Sroger } 159259014Sroger 159362112Sroger return(ENXIO); 159459014Sroger} 159559014Sroger 159659014Sroger 159759014Sroger/* 159859014Sroger * 159959014Sroger */ 160059014Srogerint 160162112Srogerbktr_close(dev_t dev, int flags, int fmt, struct proc *p) 160259014Sroger{ 160359014Sroger bktr_ptr_t bktr; 160459014Sroger int unit; 160559014Sroger 160662112Sroger unit = UNIT(dev); 160759014Sroger 160859014Sroger bktr = bktr_cd.cd_devs[unit]; 160959014Sroger 161062112Sroger switch (FUNCTION(dev)) { 161159014Sroger case VIDEO_DEV: 161262112Sroger return(video_close(bktr)); 161359014Sroger case TUNER_DEV: 161462112Sroger return(tuner_close(bktr)); 161559014Sroger case VBI_DEV: 161662112Sroger return(vbi_close(bktr)); 161759014Sroger } 161859014Sroger 161962112Sroger return(ENXIO); 162059014Sroger} 162159014Sroger 162259014Sroger/* 162359014Sroger * 162459014Sroger */ 162559014Srogerint 162662112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 162759014Sroger{ 162859014Sroger bktr_ptr_t bktr; 162959014Sroger int unit; 163059014Sroger 163162112Sroger unit = UNIT(dev); 163259014Sroger 163359014Sroger bktr = bktr_cd.cd_devs[unit]; 163459014Sroger 163562112Sroger switch (FUNCTION(dev)) { 163659014Sroger case VIDEO_DEV: 163762112Sroger return(video_read(bktr, unit, dev, uio)); 163859014Sroger case VBI_DEV: 163962112Sroger return(vbi_read(bktr, uio, ioflag)); 164059014Sroger } 164159014Sroger 164262112Sroger return(ENXIO); 164359014Sroger} 164459014Sroger 164559014Sroger 164659014Sroger/* 164759014Sroger * 164859014Sroger */ 164959014Srogerint 165062112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 165159014Sroger{ 165259014Sroger /* operation not supported */ 165362112Sroger return(EOPNOTSUPP); 165459014Sroger} 165559014Sroger 165659014Sroger/* 165759014Sroger * 165859014Sroger */ 165959014Srogerint 166062112Srogerbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr) 166159014Sroger{ 166259014Sroger bktr_ptr_t bktr; 166359014Sroger int unit; 166459014Sroger 166562112Sroger unit = UNIT(dev); 166659014Sroger 166759014Sroger bktr = bktr_cd.cd_devs[unit]; 166859014Sroger 166959014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 167062112Sroger return(ENOMEM); 167159014Sroger 167262112Sroger switch (FUNCTION(dev)) { 167359014Sroger case VIDEO_DEV: 167462112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 167559014Sroger case TUNER_DEV: 167662112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 167759014Sroger } 167859014Sroger 167962112Sroger return(ENXIO); 168059014Sroger} 168159014Sroger 168259014Sroger/* 168359014Sroger * 168459014Sroger */ 168562214Srogerpaddr_t 168662214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 168759014Sroger{ 168859014Sroger int unit; 168959014Sroger bktr_ptr_t bktr; 169059014Sroger 169162112Sroger unit = UNIT(dev); 169259014Sroger 169362112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 169462112Sroger return(-1); 169559014Sroger 169659014Sroger bktr = bktr_cd.cd_devs[unit]; 169759014Sroger 169862112Sroger if ((vaddr_t)offset < 0) 169962112Sroger return(-1); 170059014Sroger 170162112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 170262112Sroger return(-1); 170359014Sroger 170459014Sroger#ifdef __NetBSD__ 170559014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 170662112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 170759014Sroger#else 170862112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 170959014Sroger#endif 171059014Sroger} 171159014Sroger 171251694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1713