bktr_os.c revision 93023
151694Sroger/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 93023 2002-03-23 15:49:15Z nsouch $ */ 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#endif /* __FreeBSD__ */ 5451694Sroger 5559014Sroger#include "opt_bktr.h" /* include any kernel config options */ 5651694Sroger 5751694Sroger#define FIFO_RISC_DISABLED 0 5851694Sroger#define ALL_INTS_DISABLED 0 5951694Sroger 6062214Sroger 6162214Sroger/*******************/ 6262214Sroger/* *** FreeBSD *** */ 6362214Sroger/*******************/ 6462214Sroger#ifdef __FreeBSD__ 6562214Sroger 6651694Sroger#include <sys/param.h> 6751694Sroger#include <sys/systm.h> 6851694Sroger#include <sys/conf.h> 6951694Sroger#include <sys/uio.h> 7051694Sroger#include <sys/kernel.h> 7151694Sroger#include <sys/signalvar.h> 7251694Sroger#include <sys/mman.h> 7351694Sroger#include <sys/poll.h> 7470834Swollman#if __FreeBSD_version >= 500014 7570834Swollman#include <sys/selinfo.h> 7670834Swollman#else 7751694Sroger#include <sys/select.h> 7870834Swollman#endif 7951694Sroger#include <sys/vnode.h> 8051694Sroger 8151694Sroger#include <vm/vm.h> 8251694Sroger#include <vm/vm_kern.h> 8351694Sroger#include <vm/pmap.h> 8451694Sroger#include <vm/vm_extern.h> 8551694Sroger 8693023Snsouch#if (__FreeBSD_version >=400000) 8751694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 8851694Sroger#endif 8951694Sroger 9059014Sroger#if (__FreeBSD_version >=300000) 9159014Sroger#include <machine/bus_memio.h> /* used by bus space */ 9259014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 9359014Sroger#include <sys/bus.h> 9459014Sroger#endif 9559014Sroger 9651694Sroger#if (__FreeBSD_version >=400000) 9751694Sroger#include <sys/rman.h> /* used by newbus */ 9851694Sroger#include <machine/resource.h> /* used by newbus */ 9951694Sroger#endif 10051694Sroger 10167306Sroger#if (__FreeBSD_version < 500000) 10267306Sroger#include <machine/clock.h> /* for DELAY */ 10367306Sroger#endif 10459014Sroger 10551694Sroger#include <pci/pcivar.h> 10651694Sroger#include <pci/pcireg.h> 10751694Sroger 10851694Sroger#include <sys/sysctl.h> 10951694Srogerint bt848_card = -1; 11051694Srogerint bt848_tuner = -1; 11151694Srogerint bt848_reverse_mute = -1; 11251694Srogerint bt848_format = -1; 11359014Srogerint bt848_slow_msp_audio = -1; 11451694Sroger 11551694SrogerSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 11651694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 11751694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 11851694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 11951694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 12059014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 12151694Sroger 12251694Sroger#if (__FreeBSD__ == 2) 12351694Sroger#define PCIR_REVID PCI_CLASS_REG 12451694Sroger#endif 12551694Sroger 12662214Sroger#endif /* end freebsd section */ 12751694Sroger 12862214Sroger 12962214Sroger 13051694Sroger/****************/ 13151694Sroger/* *** BSDI *** */ 13251694Sroger/****************/ 13351694Sroger#ifdef __bsdi__ 13451694Sroger#endif /* __bsdi__ */ 13551694Sroger 13651694Sroger 13751694Sroger/**************************/ 13851694Sroger/* *** OpenBSD/NetBSD *** */ 13951694Sroger/**************************/ 14051694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 14162214Sroger 14262214Sroger#include <sys/param.h> 14362214Sroger#include <sys/systm.h> 14462214Sroger#include <sys/conf.h> 14562214Sroger#include <sys/uio.h> 14662214Sroger#include <sys/kernel.h> 14762214Sroger#include <sys/signalvar.h> 14862214Sroger#include <sys/mman.h> 14962214Sroger#include <sys/poll.h> 15062214Sroger#include <sys/select.h> 15162214Sroger#include <sys/vnode.h> 15262214Sroger 15362214Sroger#include <vm/vm.h> 15462214Sroger 15562214Sroger#ifndef __NetBSD__ 15662214Sroger#include <vm/vm_kern.h> 15762214Sroger#include <vm/pmap.h> 15862214Sroger#include <vm/vm_extern.h> 15962214Sroger#endif 16062214Sroger 16159014Sroger#include <sys/device.h> 16259014Sroger#include <dev/pci/pcivar.h> 16359014Sroger#include <dev/pci/pcireg.h> 16459014Sroger#include <dev/pci/pcidevs.h> 16559014Sroger 16659014Sroger#define BKTR_DEBUG 16759014Sroger#ifdef BKTR_DEBUG 16859014Srogerint bktr_debug = 0; 16959014Sroger#define DPR(x) (bktr_debug ? printf x : 0) 17059014Sroger#else 17159014Sroger#define DPR(x) 17259014Sroger#endif 17351694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 17451694Sroger 17551694Sroger 17662214Sroger#ifdef __NetBSD__ 17762214Sroger#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 17862214Sroger#include <dev/pci/bktr/bktr_reg.h> 17962214Sroger#include <dev/pci/bktr/bktr_tuner.h> 18062214Sroger#include <dev/pci/bktr/bktr_card.h> 18162214Sroger#include <dev/pci/bktr/bktr_audio.h> 18262214Sroger#include <dev/pci/bktr/bktr_core.h> 18362214Sroger#include <dev/pci/bktr/bktr_os.h> 18462214Sroger#else /* Traditional location for .h files */ 18562214Sroger#include <machine/ioctl_meteor.h> 18662214Sroger#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 18762214Sroger#include <dev/bktr/bktr_reg.h> 18862214Sroger#include <dev/bktr/bktr_tuner.h> 18962214Sroger#include <dev/bktr/bktr_card.h> 19062214Sroger#include <dev/bktr/bktr_audio.h> 19162214Sroger#include <dev/bktr/bktr_core.h> 19262214Sroger#include <dev/bktr/bktr_os.h> 19393023Snsouch 19465692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 19565392Speter#include <dev/bktr/bktr_i2c.h> 19693023Snsouch 19793023Snsouch#include "iicbb_if.h" 19893023Snsouch#include "smbus_if.h" 19962214Sroger#endif 20065392Speter#endif 20151694Sroger 20262214Sroger 20351694Sroger/****************************/ 20451694Sroger/* *** FreeBSD 4.x code *** */ 20551694Sroger/****************************/ 20651694Sroger#if (__FreeBSD_version >= 400000) 20751694Sroger 20851694Srogerstatic int bktr_probe( device_t dev ); 20951694Srogerstatic int bktr_attach( device_t dev ); 21051694Srogerstatic int bktr_detach( device_t dev ); 21151694Srogerstatic int bktr_shutdown( device_t dev ); 21251694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21351694Sroger 21451694Srogerstatic device_method_t bktr_methods[] = { 21551694Sroger /* Device interface */ 21651694Sroger DEVMETHOD(device_probe, bktr_probe), 21751694Sroger DEVMETHOD(device_attach, bktr_attach), 21851694Sroger DEVMETHOD(device_detach, bktr_detach), 21951694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 22051694Sroger 22193023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 22293023Snsouch /* iicbb interface */ 22393023Snsouch DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22493023Snsouch DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 22593023Snsouch DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 22693023Snsouch DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 22793023Snsouch DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 22893023Snsouch DEVMETHOD(iicbb_reset, bti2c_iic_reset), 22993023Snsouch 23093023Snsouch /* smbus interface */ 23193023Snsouch DEVMETHOD(smbus_callback, bti2c_smb_callback), 23293023Snsouch DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 23393023Snsouch DEVMETHOD(smbus_writew, bti2c_smb_writew), 23493023Snsouch DEVMETHOD(smbus_readb, bti2c_smb_readb), 23593023Snsouch#endif 23693023Snsouch 23751694Sroger { 0, 0 } 23851694Sroger}; 23951694Sroger 24051694Srogerstatic driver_t bktr_driver = { 24151694Sroger "bktr", 24251694Sroger bktr_methods, 24351694Sroger sizeof(struct bktr_softc), 24451694Sroger}; 24551694Sroger 24651694Srogerstatic devclass_t bktr_devclass; 24751694Sroger 24851694Srogerstatic d_open_t bktr_open; 24951694Srogerstatic d_close_t bktr_close; 25051694Srogerstatic d_read_t bktr_read; 25151694Srogerstatic d_write_t bktr_write; 25251694Srogerstatic d_ioctl_t bktr_ioctl; 25351694Srogerstatic d_mmap_t bktr_mmap; 25451694Srogerstatic d_poll_t bktr_poll; 25551694Sroger 25651694Sroger#define CDEV_MAJOR 92 25751694Srogerstatic struct cdevsw bktr_cdevsw = { 25851694Sroger /* open */ bktr_open, 25951694Sroger /* close */ bktr_close, 26051694Sroger /* read */ bktr_read, 26151694Sroger /* write */ bktr_write, 26251694Sroger /* ioctl */ bktr_ioctl, 26351694Sroger /* poll */ bktr_poll, 26451694Sroger /* mmap */ bktr_mmap, 26551694Sroger /* strategy */ nostrategy, 26651694Sroger /* name */ "bktr", 26751694Sroger /* maj */ CDEV_MAJOR, 26851694Sroger /* dump */ nodump, 26951694Sroger /* psize */ nopsize, 27051694Sroger /* flags */ 0, 27151694Sroger}; 27251694Sroger 27352995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 27467306Sroger#if (__FreeBSD_version > 410000) 27565728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27665728SrogerMODULE_VERSION(bktr, 1); 27767306Sroger#endif 27851694Sroger 27951694Sroger 28051694Sroger/* 28151694Sroger * the boot time probe routine. 28251694Sroger */ 28351694Srogerstatic int 28451694Srogerbktr_probe( device_t dev ) 28551694Sroger{ 28651694Sroger unsigned int type = pci_get_devid(dev); 28751694Sroger unsigned int rev = pci_get_revid(dev); 28851694Sroger 28967306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 29067306Sroger { 29167306Sroger switch (PCI_PRODUCT(type)) { 29267306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 29367306Sroger if (rev == 0x12) 29467306Sroger device_set_desc(dev, "BrookTree 848A"); 29567306Sroger else 29667306Sroger device_set_desc(dev, "BrookTree 848"); 29767306Sroger return 0; 29867306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 29967306Sroger device_set_desc(dev, "BrookTree 849A"); 30067306Sroger return 0; 30167306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 30267306Sroger device_set_desc(dev, "BrookTree 878"); 30367306Sroger return 0; 30467306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 30567306Sroger device_set_desc(dev, "BrookTree 879"); 30667306Sroger return 0; 30767306Sroger } 30851694Sroger }; 30951694Sroger 31051694Sroger return ENXIO; 31151694Sroger} 31251694Sroger 31351694Sroger 31451694Sroger/* 31551694Sroger * the attach routine. 31651694Sroger */ 31751694Srogerstatic int 31851694Srogerbktr_attach( device_t dev ) 31951694Sroger{ 32051694Sroger u_long latency; 32151694Sroger u_long fun; 32251694Sroger u_long val; 32351694Sroger unsigned int rev; 32451694Sroger unsigned int unit; 32551694Sroger int error = 0; 32651694Sroger#ifdef BROOKTREE_IRQ 32751694Sroger u_long old_irq, new_irq; 32851694Sroger#endif 32951694Sroger 33051694Sroger struct bktr_softc *bktr = device_get_softc(dev); 33151694Sroger 33251694Sroger unit = device_get_unit(dev); 33351694Sroger 33462112Sroger /* build the device name for bktr_name() */ 33562112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 33662112Sroger 33751694Sroger /* 33851694Sroger * Enable bus mastering and Memory Mapped device 33951694Sroger */ 34051694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 34151694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 34251694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 34351694Sroger 34451694Sroger /* 34551694Sroger * Map control/status registers. 34651694Sroger */ 34765049Sroger bktr->mem_rid = PCIR_MAPS; 34865049Sroger bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 34965049Sroger 0, ~0, 1, RF_ACTIVE); 35051694Sroger 35165049Sroger 35251694Sroger if (!bktr->res_mem) { 35351694Sroger device_printf(dev, "could not map memory\n"); 35451694Sroger error = ENXIO; 35551694Sroger goto fail; 35651694Sroger } 35759014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 35859014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 35951694Sroger 36059014Sroger 36151694Sroger /* 36251694Sroger * Disable the brooktree device 36351694Sroger */ 36459014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 36559014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 36651694Sroger 36751694Sroger 36851694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 36951694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 37051694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 37151694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 37251694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 37351694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 37451694Sroger#endif 37551694Sroger 37651694Sroger /* 37751694Sroger * Allocate our interrupt. 37851694Sroger */ 37965049Sroger bktr->irq_rid = 0; 38065049Sroger bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 38165049Sroger 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 38251694Sroger if (bktr->res_irq == NULL) { 38351694Sroger device_printf(dev, "could not map interrupt\n"); 38451694Sroger error = ENXIO; 38551694Sroger goto fail; 38651694Sroger } 38751694Sroger 38859250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 38951694Sroger bktr_intr, bktr, &bktr->res_ih); 39051694Sroger if (error) { 39151694Sroger device_printf(dev, "could not setup irq\n"); 39251694Sroger goto fail; 39351694Sroger 39451694Sroger } 39551694Sroger 39651694Sroger 39751694Sroger /* Update the Device Control Register */ 39851694Sroger /* on Bt878 and Bt879 cards */ 39951694Sroger fun = pci_read_config( dev, 0x40, 2); 40051694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 40151694Sroger 40251694Sroger#if defined( BKTR_430_FX_MODE ) 40351694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 40451694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 40551694Sroger#endif 40651694Sroger 40751694Sroger#if defined( BKTR_SIS_VIA_MODE ) 40851694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 40951694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 41051694Sroger OPTi chipset motherboards too */ 41151694Sroger#endif 41251694Sroger pci_write_config(dev, 0x40, fun, 2); 41351694Sroger 41465692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 41593023Snsouch if (bt848_i2c_attach(dev)) 41651694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 41751694Sroger#endif 41851694Sroger 41951694Sroger/* 42051694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 42151694Sroger * you have more than four, then 16 would probably be a better value. 42251694Sroger */ 42351694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 42451694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 42551694Sroger#endif 42651694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 42751694Sroger latency = (latency >> 8) & 0xff; 42851694Sroger if ( bootverbose ) { 42951694Sroger if (latency) 43051694Sroger printf("brooktree%d: PCI bus latency is", unit); 43151694Sroger else 43251694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 43351694Sroger unit); 43451694Sroger } 43551694Sroger if ( !latency ) { 43651694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 43751694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 43851694Sroger } 43951694Sroger if ( bootverbose ) { 44051694Sroger printf(" %d.\n", (int) latency); 44151694Sroger } 44251694Sroger 44351694Sroger /* read the pci device id and revision id */ 44451694Sroger fun = pci_get_devid(dev); 44551694Sroger rev = pci_get_revid(dev); 44651694Sroger 44751694Sroger /* call the common attach code */ 44851694Sroger common_bktr_attach( bktr, unit, fun, rev ); 44951694Sroger 45067306Sroger /* make the device entries */ 45167306Sroger bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 45267306Sroger 0, 0, 0444, "bktr%d", unit); 45367306Sroger bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 45467306Sroger 0, 0, 0444, "tuner%d", unit); 45567306Sroger bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 45667306Sroger 0, 0, 0444, "vbi%d" , unit); 45751694Sroger 45867306Sroger 45967306Sroger /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 46067306Sroger /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 46167306Sroger#if (__FreeBSD_version >=500000) 46267306Sroger if (unit == 0) { 46367306Sroger bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 46467306Sroger bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 46567306Sroger bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 46667306Sroger } 46767306Sroger#endif 46867306Sroger 46951694Sroger return 0; 47051694Sroger 47151694Srogerfail: 47265049Sroger if (bktr->res_irq) 47365049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 47465049Sroger if (bktr->res_mem) 47565049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 47651694Sroger return error; 47751694Sroger 47851694Sroger} 47951694Sroger 48051694Sroger/* 48151694Sroger * the detach routine. 48251694Sroger */ 48351694Srogerstatic int 48451694Srogerbktr_detach( device_t dev ) 48551694Sroger{ 48667366Sroger unsigned int unit; 48767366Sroger 48851694Sroger struct bktr_softc *bktr = device_get_softc(dev); 48951694Sroger 49067366Sroger unit = device_get_unit(dev); 49167366Sroger 49251694Sroger /* Disable the brooktree device */ 49359014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 49459014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49551694Sroger 49693023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 49793023Snsouch if (bt848_i2c_detach(dev)) 49893023Snsouch printf("bktr%d: i2c_attach: can't attach\n", unit); 49993023Snsouch#endif 50093023Snsouch 50167306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50267306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 50367306Sroger /* then reload the main bktr driver module */ 50451694Sroger 50567306Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices */ 50667306Sroger destroy_dev(bktr->vbidev); 50767306Sroger destroy_dev(bktr->tunerdev); 50867306Sroger destroy_dev(bktr->bktrdev); 50967306Sroger 51067306Sroger /* If this is unit 0, then destroy the alias entries too */ 51167306Sroger#if (__FreeBSD_version >=500000) 51267306Sroger if (unit == 0) { 51367306Sroger destroy_dev(bktr->vbidev_alias); 51467306Sroger destroy_dev(bktr->tunerdev_alias); 51567306Sroger destroy_dev(bktr->bktrdev_alias); 51667306Sroger } 51767306Sroger#endif 51867306Sroger 51951694Sroger /* 52051694Sroger * Deallocate resources. 52151694Sroger */ 52251694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 52365049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 52465049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 52565049Sroger 52651694Sroger return 0; 52751694Sroger} 52851694Sroger 52951694Sroger/* 53051694Sroger * the shutdown routine. 53151694Sroger */ 53251694Srogerstatic int 53351694Srogerbktr_shutdown( device_t dev ) 53451694Sroger{ 53551694Sroger struct bktr_softc *bktr = device_get_softc(dev); 53651694Sroger 53751694Sroger /* Disable the brooktree device */ 53859014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 54051694Sroger 54151694Sroger return 0; 54251694Sroger} 54351694Sroger 54451694Sroger 54551694Sroger/* 54651694Sroger * Special Memory Allocation 54751694Sroger */ 54851694Srogervm_offset_t 54951694Srogerget_bktr_mem( int unit, unsigned size ) 55051694Sroger{ 55151694Sroger vm_offset_t addr = 0; 55251694Sroger 55351694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 55451694Sroger if (addr == 0) 55551694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 55651694Sroger if (addr == 0) { 55751694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 55851694Sroger unit, size); 55951694Sroger } 56051694Sroger 56151694Sroger return( addr ); 56251694Sroger} 56351694Sroger 56451694Sroger 56551694Sroger/*--------------------------------------------------------- 56651694Sroger** 56751694Sroger** BrookTree 848 character device driver routines 56851694Sroger** 56951694Sroger**--------------------------------------------------------- 57051694Sroger*/ 57151694Sroger 57251694Sroger#define VIDEO_DEV 0x00 57351694Sroger#define TUNER_DEV 0x01 57451694Sroger#define VBI_DEV 0x02 57551694Sroger 57651694Sroger#define UNIT(x) ((x) & 0x0f) 57751694Sroger#define FUNCTION(x) (x >> 4) 57851694Sroger 57951694Sroger/* 58051694Sroger * 58151694Sroger */ 58251694Srogerint 58383366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 58451694Sroger{ 58551694Sroger bktr_ptr_t bktr; 58651694Sroger int unit; 58751694Sroger int result; 58851694Sroger 58951694Sroger unit = UNIT( minor(dev) ); 59051694Sroger 59151694Sroger /* Get the device data */ 59251694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 59351694Sroger if (bktr == NULL) { 59451694Sroger /* the device is no longer valid/functioning */ 59551694Sroger return (ENXIO); 59651694Sroger } 59751694Sroger 59851694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 59951694Sroger return( ENXIO ); 60051694Sroger 60151694Sroger /* Record that the device is now busy */ 60251694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 60351694Sroger 60451694Sroger 60551694Sroger if (bt848_card != -1) { 60651694Sroger if ((bt848_card >> 8 == unit ) && 60751694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 60851694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 60951694Sroger bktr->bt848_card = (bt848_card & 0xff); 61051694Sroger probeCard(bktr, FALSE, unit); 61151694Sroger } 61251694Sroger } 61351694Sroger } 61451694Sroger 61551694Sroger if (bt848_tuner != -1) { 61651694Sroger if ((bt848_tuner >> 8 == unit ) && 61751694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 61851694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 61951694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 62051694Sroger probeCard(bktr, FALSE, unit); 62151694Sroger } 62251694Sroger } 62351694Sroger } 62451694Sroger 62551694Sroger if (bt848_reverse_mute != -1) { 62659014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 62751694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 62851694Sroger } 62951694Sroger } 63051694Sroger 63159014Sroger if (bt848_slow_msp_audio != -1) { 63259014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 63359014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 63459014Sroger } 63559014Sroger } 63659014Sroger 63751694Sroger switch ( FUNCTION( minor(dev) ) ) { 63851694Sroger case VIDEO_DEV: 63951694Sroger result = video_open( bktr ); 64051694Sroger break; 64151694Sroger case TUNER_DEV: 64251694Sroger result = tuner_open( bktr ); 64351694Sroger break; 64451694Sroger case VBI_DEV: 64551694Sroger result = vbi_open( bktr ); 64651694Sroger break; 64751694Sroger default: 64851694Sroger result = ENXIO; 64951694Sroger break; 65051694Sroger } 65151694Sroger 65251694Sroger /* If there was an error opening the device, undo the busy status */ 65351694Sroger if (result != 0) 65451694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 65551694Sroger return( result ); 65651694Sroger} 65751694Sroger 65851694Sroger 65951694Sroger/* 66051694Sroger * 66151694Sroger */ 66251694Srogerint 66383366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 66451694Sroger{ 66551694Sroger bktr_ptr_t bktr; 66651694Sroger int unit; 66751694Sroger int result; 66851694Sroger 66951694Sroger unit = UNIT( minor(dev) ); 67051694Sroger 67151694Sroger /* Get the device data */ 67251694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 67351694Sroger if (bktr == NULL) { 67451694Sroger /* the device is no longer valid/functioning */ 67551694Sroger return (ENXIO); 67651694Sroger } 67751694Sroger 67851694Sroger switch ( FUNCTION( minor(dev) ) ) { 67951694Sroger case VIDEO_DEV: 68051694Sroger result = video_close( bktr ); 68151694Sroger break; 68251694Sroger case TUNER_DEV: 68351694Sroger result = tuner_close( bktr ); 68451694Sroger break; 68551694Sroger case VBI_DEV: 68651694Sroger result = vbi_close( bktr ); 68751694Sroger break; 68851694Sroger default: 68951694Sroger return (ENXIO); 69051694Sroger break; 69151694Sroger } 69251694Sroger 69351694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 69451694Sroger return( result ); 69551694Sroger} 69651694Sroger 69751694Sroger 69851694Sroger/* 69951694Sroger * 70051694Sroger */ 70151694Srogerint 70251694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 70351694Sroger{ 70451694Sroger bktr_ptr_t bktr; 70551694Sroger int unit; 70651694Sroger 70751694Sroger unit = UNIT(minor(dev)); 70851694Sroger 70951694Sroger /* Get the device data */ 71051694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 71151694Sroger if (bktr == NULL) { 71251694Sroger /* the device is no longer valid/functioning */ 71351694Sroger return (ENXIO); 71451694Sroger } 71551694Sroger 71651694Sroger switch ( FUNCTION( minor(dev) ) ) { 71751694Sroger case VIDEO_DEV: 71851694Sroger return( video_read( bktr, unit, dev, uio ) ); 71951694Sroger case VBI_DEV: 72051694Sroger return( vbi_read( bktr, uio, ioflag ) ); 72151694Sroger } 72251694Sroger return( ENXIO ); 72351694Sroger} 72451694Sroger 72551694Sroger 72651694Sroger/* 72751694Sroger * 72851694Sroger */ 72951694Srogerint 73051694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 73151694Sroger{ 73251694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 73351694Sroger} 73451694Sroger 73551694Sroger 73651694Sroger/* 73751694Sroger * 73851694Sroger */ 73951694Srogerint 74083366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 74151694Sroger{ 74251694Sroger bktr_ptr_t bktr; 74351694Sroger int unit; 74451694Sroger 74551694Sroger unit = UNIT(minor(dev)); 74651694Sroger 74751694Sroger /* Get the device data */ 74851694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 74951694Sroger if (bktr == NULL) { 75051694Sroger /* the device is no longer valid/functioning */ 75151694Sroger return (ENXIO); 75251694Sroger } 75351694Sroger 75451694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 75551694Sroger return( ENOMEM ); 75651694Sroger 75751694Sroger switch ( FUNCTION( minor(dev) ) ) { 75851694Sroger case VIDEO_DEV: 75983366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 76051694Sroger case TUNER_DEV: 76183366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 76251694Sroger } 76351694Sroger 76451694Sroger return( ENXIO ); 76551694Sroger} 76651694Sroger 76751694Sroger 76851694Sroger/* 76951694Sroger * 77051694Sroger */ 77151694Srogerint 77251694Srogerbktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 77351694Sroger{ 77451694Sroger int unit; 77551694Sroger bktr_ptr_t bktr; 77651694Sroger 77751694Sroger unit = UNIT(minor(dev)); 77851694Sroger 77951694Sroger if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 78051694Sroger return( -1 ); 78151694Sroger 78251694Sroger /* Get the device data */ 78351694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 78451694Sroger if (bktr == NULL) { 78551694Sroger /* the device is no longer valid/functioning */ 78651694Sroger return (ENXIO); 78751694Sroger } 78851694Sroger 78951694Sroger if (nprot & PROT_EXEC) 79051694Sroger return( -1 ); 79151694Sroger 79251694Sroger if (offset < 0) 79351694Sroger return( -1 ); 79451694Sroger 79551694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 79651694Sroger return( -1 ); 79751694Sroger 79859250Sroger return( atop(vtophys(bktr->bigbuf) + offset) ); 79951694Sroger} 80051694Sroger 80183366Sjulianint bktr_poll( dev_t dev, int events, struct thread *td) 80251694Sroger{ 80351694Sroger int unit; 80451694Sroger bktr_ptr_t bktr; 80551694Sroger int revents = 0; 80659277Sroger DECLARE_INTR_MASK(s); 80751694Sroger 80851694Sroger unit = UNIT(minor(dev)); 80951694Sroger 81051694Sroger /* Get the device data */ 81151694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 81251694Sroger if (bktr == NULL) { 81351694Sroger /* the device is no longer valid/functioning */ 81451694Sroger return (ENXIO); 81551694Sroger } 81651694Sroger 81759277Sroger DISABLE_INTR(s); 81851694Sroger 81951694Sroger if (events & (POLLIN | POLLRDNORM)) { 82051694Sroger 82151694Sroger switch ( FUNCTION( minor(dev) ) ) { 82251694Sroger case VBI_DEV: 82351694Sroger if(bktr->vbisize == 0) 82483366Sjulian selrecord(td, &bktr->vbi_select); 82551694Sroger else 82651694Sroger revents |= events & (POLLIN | POLLRDNORM); 82751694Sroger break; 82851694Sroger } 82951694Sroger } 83051694Sroger 83159250Sroger ENABLE_INTR(s); 83251694Sroger 83351694Sroger return (revents); 83451694Sroger} 83551694Sroger 83651694Sroger#endif /* FreeBSD 4.x specific kernel interface routines */ 83751694Sroger 83851694Sroger/**********************************/ 83951694Sroger/* *** FreeBSD 2.2.x and 3.x *** */ 84051694Sroger/**********************************/ 84151694Sroger 84251694Sroger#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3)) 84351694Sroger 84451694Srogerstatic bktr_reg_t brooktree[ NBKTR ]; 84551694Sroger 84651694Srogerstatic const char* bktr_probe( pcici_t tag, pcidi_t type ); 84751694Srogerstatic void bktr_attach( pcici_t tag, int unit ); 84851694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 84951694Sroger 85051694Srogerstatic u_long bktr_count; 85151694Sroger 85251694Srogerstatic struct pci_device bktr_device = { 85351694Sroger "bktr", 85451694Sroger bktr_probe, 85551694Sroger bktr_attach, 85651694Sroger &bktr_count 85751694Sroger}; 85851694Sroger 85951694SrogerDATA_SET (pcidevice_set, bktr_device); 86051694Sroger 86151694Srogerstatic d_open_t bktr_open; 86251694Srogerstatic d_close_t bktr_close; 86351694Srogerstatic d_read_t bktr_read; 86451694Srogerstatic d_write_t bktr_write; 86551694Srogerstatic d_ioctl_t bktr_ioctl; 86651694Srogerstatic d_mmap_t bktr_mmap; 86751694Srogerstatic d_poll_t bktr_poll; 86851694Sroger 86951694Sroger#define CDEV_MAJOR 92 87051694Srogerstatic struct cdevsw bktr_cdevsw = 87151694Sroger{ 87251694Sroger bktr_open, bktr_close, bktr_read, bktr_write, 87351694Sroger bktr_ioctl, nostop, nullreset, nodevtotty, 87451694Sroger bktr_poll, bktr_mmap, NULL, "bktr", 87551694Sroger NULL, -1 87651694Sroger}; 87751694Sroger 87851694Sroger/* 87951694Sroger * the boot time probe routine. 88051694Sroger */ 88151694Srogerstatic const char* 88251694Srogerbktr_probe( pcici_t tag, pcidi_t type ) 88351694Sroger{ 88451694Sroger unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff; 88567306Sroger 88667306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 88767306Sroger { 88867306Sroger switch (PCI_PRODUCT(type)) { 88967306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 89067306Sroger if (rev == 0x12) return("BrookTree 848A"); 89167306Sroger else return("BrookTree 848"); 89267306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 89367306Sroger return("BrookTree 849A"); 89467306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 89567306Sroger return("BrookTree 878"); 89667306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 89767306Sroger return("BrookTree 879"); 89867306Sroger } 89951694Sroger }; 90051694Sroger 90151694Sroger return ((char *)0); 90251694Sroger} 90351694Sroger 90451694Sroger/* 90551694Sroger * the attach routine. 90651694Sroger */ 90751694Srogerstatic void 90851694Srogerbktr_attach( pcici_t tag, int unit ) 90951694Sroger{ 91051694Sroger bktr_ptr_t bktr; 91151694Sroger u_long latency; 91251694Sroger u_long fun; 91351694Sroger unsigned int rev; 91459014Sroger unsigned long base; 91551694Sroger#ifdef BROOKTREE_IRQ 91651694Sroger u_long old_irq, new_irq; 91751694Sroger#endif 91851694Sroger 91951694Sroger bktr = &brooktree[unit]; 92051694Sroger 92151694Sroger if (unit >= NBKTR) { 92251694Sroger printf("brooktree%d: attach: only %d units configured.\n", 92351694Sroger unit, NBKTR); 92451694Sroger printf("brooktree%d: attach: invalid unit number.\n", unit); 92551694Sroger return; 92651694Sroger } 92751694Sroger 92862112Sroger /* build the device name for bktr_name() */ 92962112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 93062112Sroger 93151694Sroger /* Enable Memory Mapping */ 93251694Sroger fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 93351694Sroger pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2); 93451694Sroger 93551694Sroger /* Enable Bus Mastering */ 93651694Sroger fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 93751694Sroger pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4); 93851694Sroger 93951694Sroger bktr->tag = tag; 94051694Sroger 94151694Sroger 94251694Sroger /* 94351694Sroger * Map control/status registers 94451694Sroger */ 94559014Sroger pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base, 94651694Sroger &bktr->phys_base ); 94759014Sroger#if (__FreeBSD_version >= 300000) 94859014Sroger bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */ 94959014Sroger bktr->memh = (bus_space_handle_t)base; /* XXX functions here */ 95059014Sroger#endif 95151694Sroger 95251694Sroger /* 95351694Sroger * Disable the brooktree device 95451694Sroger */ 95559014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 95659014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 95751694Sroger 95851694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 95951694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 96051694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 96151694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 96251694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 96351694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 96451694Sroger#endif 96551694Sroger 96651694Sroger /* 96751694Sroger * setup the interrupt handling routine 96851694Sroger */ 96959250Sroger pci_map_int(tag, bktr_intr, (void*) bktr, &tty_imask); 97051694Sroger 97151694Sroger 97251694Sroger /* Update the Device Control Register */ 97351694Sroger /* on Bt878 and Bt879 cards */ 97451694Sroger fun = pci_conf_read(tag, 0x40); 97551694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 97651694Sroger 97751694Sroger#if defined( BKTR_430_FX_MODE ) 97851694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 97951694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 98051694Sroger#endif 98151694Sroger 98251694Sroger#if defined( BKTR_SIS_VIA_MODE ) 98351694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 98451694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 98551694Sroger OPTi chipset motherboards too */ 98651694Sroger#endif 98751694Sroger pci_conf_write(tag, 0x40, fun); 98851694Sroger 98965692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 99093023Snsouch if (bt848_i2c_attach(dev)) 99151694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 99251694Sroger#endif 99351694Sroger 99451694Sroger/* 99551694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 99651694Sroger * you have more than four, then 16 would probably be a better value. 99751694Sroger */ 99851694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 99951694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 100051694Sroger#endif 100151694Sroger latency = pci_conf_read(tag, PCI_LATENCY_TIMER); 100251694Sroger latency = (latency >> 8) & 0xff; 100351694Sroger if ( bootverbose ) { 100451694Sroger if (latency) 100551694Sroger printf("brooktree%d: PCI bus latency is", unit); 100651694Sroger else 100751694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 100851694Sroger unit); 100951694Sroger } 101051694Sroger if ( !latency ) { 101151694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 101251694Sroger pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); 101351694Sroger } 101451694Sroger if ( bootverbose ) { 101551694Sroger printf(" %d.\n", (int) latency); 101651694Sroger } 101751694Sroger 101851694Sroger 101951694Sroger /* read the pci device id and revision id */ 102051694Sroger fun = pci_conf_read(tag, PCI_ID_REG); 102151694Sroger rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff; 102251694Sroger 102351694Sroger /* call the common attach code */ 102451694Sroger common_bktr_attach( bktr, unit, fun, rev ); 102551694Sroger 102651694Sroger} 102751694Sroger 102851694Sroger 102951694Sroger/* 103051694Sroger * Special Memory Allocation 103151694Sroger */ 103251694Srogervm_offset_t 103351694Srogerget_bktr_mem( int unit, unsigned size ) 103451694Sroger{ 103551694Sroger vm_offset_t addr = 0; 103651694Sroger 103751694Sroger addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24); 103851694Sroger if (addr == 0) 103951694Sroger addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 104051694Sroger PAGE_SIZE); 104151694Sroger if (addr == 0) { 104251694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 104351694Sroger unit, size); 104451694Sroger } 104551694Sroger 104651694Sroger return( addr ); 104751694Sroger} 104851694Sroger 104951694Sroger/*--------------------------------------------------------- 105051694Sroger** 105151694Sroger** BrookTree 848 character device driver routines 105251694Sroger** 105351694Sroger**--------------------------------------------------------- 105451694Sroger*/ 105551694Sroger 105651694Sroger 105751694Sroger#define VIDEO_DEV 0x00 105851694Sroger#define TUNER_DEV 0x01 105951694Sroger#define VBI_DEV 0x02 106051694Sroger 106151694Sroger#define UNIT(x) ((x) & 0x0f) 106251694Sroger#define FUNCTION(x) ((x >> 4) & 0x0f) 106351694Sroger 106451694Sroger 106551694Sroger/* 106651694Sroger * 106751694Sroger */ 106851694Srogerint 106983366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 107051694Sroger{ 107151694Sroger bktr_ptr_t bktr; 107251694Sroger int unit; 107351694Sroger 107451694Sroger unit = UNIT( minor(dev) ); 107551694Sroger if (unit >= NBKTR) /* unit out of range */ 107651694Sroger return( ENXIO ); 107751694Sroger 107851694Sroger bktr = &(brooktree[ unit ]); 107951694Sroger 108051694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 108151694Sroger return( ENXIO ); 108251694Sroger 108351694Sroger 108451694Sroger if (bt848_card != -1) { 108551694Sroger if ((bt848_card >> 8 == unit ) && 108651694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 108751694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 108851694Sroger bktr->bt848_card = (bt848_card & 0xff); 108951694Sroger probeCard(bktr, FALSE, unit); 109051694Sroger } 109151694Sroger } 109251694Sroger } 109351694Sroger 109451694Sroger if (bt848_tuner != -1) { 109551694Sroger if ((bt848_tuner >> 8 == unit ) && 109651694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 109751694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 109851694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 109951694Sroger probeCard(bktr, FALSE, unit); 110051694Sroger } 110151694Sroger } 110251694Sroger } 110351694Sroger 110451694Sroger if (bt848_reverse_mute != -1) { 110559014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 110651694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 110751694Sroger } 110851694Sroger } 110951694Sroger 111059014Sroger if (bt848_slow_msp_audio != -1) { 111159014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 111259014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 111359014Sroger } 111459014Sroger } 111551694Sroger 111651694Sroger switch ( FUNCTION( minor(dev) ) ) { 111751694Sroger case VIDEO_DEV: 111851694Sroger return( video_open( bktr ) ); 111951694Sroger case TUNER_DEV: 112051694Sroger return( tuner_open( bktr ) ); 112151694Sroger case VBI_DEV: 112251694Sroger return( vbi_open( bktr ) ); 112351694Sroger } 112451694Sroger return( ENXIO ); 112551694Sroger} 112651694Sroger 112751694Sroger 112851694Sroger/* 112951694Sroger * 113051694Sroger */ 113151694Srogerint 113283366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 113351694Sroger{ 113451694Sroger bktr_ptr_t bktr; 113551694Sroger int unit; 113651694Sroger 113751694Sroger unit = UNIT( minor(dev) ); 113851694Sroger if (unit >= NBKTR) /* unit out of range */ 113951694Sroger return( ENXIO ); 114051694Sroger 114151694Sroger bktr = &(brooktree[ unit ]); 114251694Sroger 114351694Sroger switch ( FUNCTION( minor(dev) ) ) { 114451694Sroger case VIDEO_DEV: 114551694Sroger return( video_close( bktr ) ); 114651694Sroger case TUNER_DEV: 114751694Sroger return( tuner_close( bktr ) ); 114851694Sroger case VBI_DEV: 114951694Sroger return( vbi_close( bktr ) ); 115051694Sroger } 115151694Sroger 115251694Sroger return( ENXIO ); 115351694Sroger} 115451694Sroger 115551694Sroger/* 115651694Sroger * 115751694Sroger */ 115851694Srogerint 115951694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 116051694Sroger{ 116151694Sroger bktr_ptr_t bktr; 116251694Sroger int unit; 116351694Sroger 116451694Sroger unit = UNIT(minor(dev)); 116551694Sroger if (unit >= NBKTR) /* unit out of range */ 116651694Sroger return( ENXIO ); 116751694Sroger 116851694Sroger bktr = &(brooktree[unit]); 116951694Sroger 117051694Sroger switch ( FUNCTION( minor(dev) ) ) { 117151694Sroger case VIDEO_DEV: 117251694Sroger return( video_read( bktr, unit, dev, uio ) ); 117351694Sroger case VBI_DEV: 117451694Sroger return( vbi_read( bktr, uio, ioflag ) ); 117551694Sroger } 117651694Sroger return( ENXIO ); 117751694Sroger} 117851694Sroger 117951694Sroger 118051694Sroger/* 118151694Sroger * 118251694Sroger */ 118351694Srogerint 118451694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 118551694Sroger{ 118651694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 118751694Sroger} 118851694Sroger 118951694Sroger/* 119051694Sroger * 119151694Sroger */ 119251694Srogerint 119383366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 119451694Sroger{ 119551694Sroger bktr_ptr_t bktr; 119651694Sroger int unit; 119751694Sroger 119851694Sroger unit = UNIT(minor(dev)); 119951694Sroger if (unit >= NBKTR) /* unit out of range */ 120051694Sroger return( ENXIO ); 120151694Sroger 120251694Sroger bktr = &(brooktree[ unit ]); 120351694Sroger 120451694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 120551694Sroger return( ENOMEM ); 120651694Sroger 120751694Sroger switch ( FUNCTION( minor(dev) ) ) { 120851694Sroger case VIDEO_DEV: 120983366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 121051694Sroger case TUNER_DEV: 121183366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 121251694Sroger } 121351694Sroger 121451694Sroger return( ENXIO ); 121551694Sroger} 121651694Sroger 121751694Sroger/* 121851694Sroger * bktr_mmap. 121951694Sroger * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually 122052593Sroger * edit the line below and change "vm_offset_t" to "int" 122151694Sroger */ 122251694Srogerint bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 122351694Sroger 122451694Sroger{ 122551694Sroger int unit; 122651694Sroger bktr_ptr_t bktr; 122751694Sroger 122851694Sroger unit = UNIT(minor(dev)); 122951694Sroger 123051694Sroger if (unit >= NBKTR || FUNCTION(minor(dev)) > 0) 123151694Sroger return( -1 ); 123251694Sroger 123351694Sroger bktr = &(brooktree[ unit ]); 123451694Sroger 123551694Sroger if (nprot & PROT_EXEC) 123651694Sroger return( -1 ); 123751694Sroger 123851694Sroger if (offset < 0) 123951694Sroger return( -1 ); 124051694Sroger 124151694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 124251694Sroger return( -1 ); 124351694Sroger 124451694Sroger return( i386_btop(vtophys(bktr->bigbuf) + offset) ); 124551694Sroger} 124651694Sroger 124783366Sjulianint bktr_poll( dev_t dev, int events, struct thread *td) 124851694Sroger{ 124951694Sroger int unit; 125051694Sroger bktr_ptr_t bktr; 125151694Sroger int revents = 0; 125251694Sroger 125351694Sroger unit = UNIT(minor(dev)); 125451694Sroger 125551694Sroger if (unit >= NBKTR) 125651694Sroger return( -1 ); 125751694Sroger 125851694Sroger bktr = &(brooktree[ unit ]); 125951694Sroger 126051694Sroger disable_intr(); 126151694Sroger 126251694Sroger if (events & (POLLIN | POLLRDNORM)) { 126351694Sroger 126451694Sroger switch ( FUNCTION( minor(dev) ) ) { 126551694Sroger case VBI_DEV: 126651694Sroger if(bktr->vbisize == 0) 126751694Sroger selrecord(p, &bktr->vbi_select); 126851694Sroger else 126951694Sroger revents |= events & (POLLIN | POLLRDNORM); 127051694Sroger break; 127151694Sroger } 127251694Sroger } 127351694Sroger 127451694Sroger enable_intr(); 127551694Sroger 127651694Sroger return (revents); 127751694Sroger} 127851694Sroger 127951694Sroger 128051694Sroger#endif /* FreeBSD 2.2.x and 3.x specific kernel interface routines */ 128151694Sroger 128251694Sroger 128351694Sroger/*****************/ 128451694Sroger/* *** BSDI *** */ 128551694Sroger/*****************/ 128651694Sroger 128751694Sroger#if defined(__bsdi__) 128851694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 128951694Sroger 129051694Sroger 129151694Sroger/*****************************/ 129251694Sroger/* *** OpenBSD / NetBSD *** */ 129351694Sroger/*****************************/ 129451694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 129559014Sroger 129659014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 129759014Sroger 129859014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 129959014Sroger 130059014Sroger#define bktr_open bktropen 130159014Sroger#define bktr_close bktrclose 130259014Sroger#define bktr_read bktrread 130359014Sroger#define bktr_write bktrwrite 130459014Sroger#define bktr_ioctl bktrioctl 130559014Sroger#define bktr_mmap bktrmmap 130659014Sroger 130759014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 130859014Sroger vm_offset_t, vm_offset_t); 130959014Sroger 131062112Sroger#if defined(__OpenBSD__) 131192739Salfredstatic int bktr_probe(struct device *, void *, void *); 131259014Sroger#else 131392739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 131459014Sroger#endif 131592739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 131659014Sroger 131759014Srogerstruct cfattach bktr_ca = { 131859014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 131959014Sroger}; 132059014Sroger 132159014Sroger#if defined(__NetBSD__) 132259014Srogerextern struct cfdriver bktr_cd; 132359014Sroger#else 132459014Srogerstruct cfdriver bktr_cd = { 132559014Sroger NULL, "bktr", DV_DULL 132659014Sroger}; 132759014Sroger#endif 132859014Sroger 132962112Srogerint 133062112Srogerbktr_probe(parent, match, aux) 133162112Sroger struct device *parent; 133262112Sroger#if defined(__OpenBSD__) 133359014Sroger void *match; 133459014Sroger#else 133559014Sroger struct cfdata *match; 133659014Sroger#endif 133759014Sroger void *aux; 133859014Sroger{ 133959014Sroger struct pci_attach_args *pa = aux; 134059014Sroger 134159014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 134259014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 134359014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 134459014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 134559014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 134659014Sroger return 1; 134759014Sroger 134859014Sroger return 0; 134959014Sroger} 135059014Sroger 135159014Sroger 135259014Sroger/* 135359014Sroger * the attach routine. 135459014Sroger */ 135559014Srogerstatic void 135662112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 135759014Sroger{ 135859014Sroger bktr_ptr_t bktr; 135959014Sroger u_long latency; 136059014Sroger u_long fun; 136159014Sroger unsigned int rev; 136259014Sroger 136359014Sroger#if defined(__OpenBSD__) 136459014Sroger struct pci_attach_args *pa = aux; 136559014Sroger pci_chipset_tag_t pc = pa->pa_pc; 136659014Sroger 136759014Sroger pci_intr_handle_t ih; 136859014Sroger const char *intrstr; 136959014Sroger int retval; 137059014Sroger int unit; 137159014Sroger 137259014Sroger bktr = (bktr_ptr_t)self; 137359014Sroger unit = bktr->bktr_dev.dv_unit; 137459014Sroger 137559014Sroger bktr->pc = pa->pa_pc; 137659014Sroger bktr->tag = pa->pa_tag; 137759014Sroger bktr->dmat = pa->pa_dmat; 137859014Sroger 137959014Sroger /* 138059014Sroger * map memory 138159014Sroger */ 138259014Sroger bktr->memt = pa->pa_memt; 138359014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 138459014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 138559014Sroger if (!retval) 138659014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 138759014Sroger bktr->obmemsz, 0, &bktr->memh); 138859014Sroger if (retval) { 138959014Sroger printf(": couldn't map memory\n"); 139059014Sroger return; 139159014Sroger } 139259014Sroger 139359014Sroger 139459014Sroger /* 139559014Sroger * map interrupt 139659014Sroger */ 139759014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 139859014Sroger pa->pa_intrline, &ih)) { 139959014Sroger printf(": couldn't map interrupt\n"); 140059014Sroger return; 140159014Sroger } 140259014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 140359014Sroger 140459014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 140559014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 140659014Sroger if (bktr->ih == NULL) { 140759014Sroger printf(": couldn't establish interrupt"); 140859014Sroger if (intrstr != NULL) 140959014Sroger printf(" at %s", intrstr); 141059014Sroger printf("\n"); 141159014Sroger return; 141259014Sroger } 141359014Sroger 141459014Sroger if (intrstr != NULL) 141559014Sroger printf(": %s\n", intrstr); 141659014Sroger#endif /* __OpenBSD__ */ 141759014Sroger 141859014Sroger#if defined(__NetBSD__) 141959014Sroger struct pci_attach_args *pa = aux; 142059014Sroger pci_intr_handle_t ih; 142159014Sroger const char *intrstr; 142259014Sroger int retval; 142359014Sroger int unit; 142459014Sroger 142559014Sroger bktr = (bktr_ptr_t)self; 142659014Sroger unit = bktr->bktr_dev.dv_unit; 142759014Sroger bktr->dmat = pa->pa_dmat; 142859014Sroger 142959014Sroger printf("\n"); 143059014Sroger 143159014Sroger /* 143259014Sroger * map memory 143359014Sroger */ 143459014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 143562112Sroger PCI_MAPREG_TYPE_MEM 143662112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 143762112Sroger &bktr->memt, &bktr->memh, NULL, 143862112Sroger &bktr->obmemsz); 143962112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 144062112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 144159014Sroger if (retval) { 144262112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 144359014Sroger return; 144459014Sroger } 144559014Sroger 144659014Sroger /* 144759014Sroger * Disable the brooktree device 144859014Sroger */ 144959014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 145059014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 145159014Sroger 145259014Sroger /* 145359014Sroger * map interrupt 145459014Sroger */ 145559014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 145659014Sroger pa->pa_intrline, &ih)) { 145762112Sroger printf("%s: couldn't map interrupt\n", 145862112Sroger bktr_name(bktr)); 145959014Sroger return; 146059014Sroger } 146159014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 146259014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 146359014Sroger bktr_intr, bktr); 146459014Sroger if (bktr->ih == NULL) { 146559014Sroger printf("%s: couldn't establish interrupt", 146662112Sroger bktr_name(bktr)); 146762112Sroger if (intrstr != NULL) 146862112Sroger printf(" at %s", intrstr); 146962112Sroger printf("\n"); 147062112Sroger return; 147159014Sroger } 147259014Sroger if (intrstr != NULL) 147362112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 147459014Sroger intrstr); 147559014Sroger#endif /* __NetBSD__ */ 147659014Sroger 147759014Sroger/* 147859014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 147959014Sroger * you have more than four, then 16 would probably be a better value. 148059014Sroger */ 148159014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 148259014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 148359014Sroger#endif 148459014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 148559014Sroger latency = (latency >> 8) & 0xff; 148659014Sroger 148762112Sroger if (!latency) { 148862112Sroger if (bootverbose) { 148959014Sroger printf("%s: PCI bus latency was 0 changing to %d", 149062112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 149159014Sroger } 149259014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 149359014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 149459014Sroger PCI_LATENCY_TIMER, latency<<8); 149559014Sroger } 149659014Sroger 149759014Sroger 149862112Sroger /* Enabled Bus Master 149962112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 150062112Sroger boot) */ 150159014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 150262112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 150362112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 150459014Sroger 150559014Sroger /* read the pci id and determine the card type */ 150659014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 150759014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 150859014Sroger 150962112Sroger common_bktr_attach(bktr, unit, fun, rev); 151059014Sroger} 151159014Sroger 151259014Sroger 151359014Sroger/* 151459014Sroger * Special Memory Allocation 151559014Sroger */ 151659014Srogervm_offset_t 151759014Srogerget_bktr_mem(bktr, dmapp, size) 151859014Sroger bktr_ptr_t bktr; 151959014Sroger bus_dmamap_t *dmapp; 152059014Sroger unsigned int size; 152159014Sroger{ 152259014Sroger bus_dma_tag_t dmat = bktr->dmat; 152359014Sroger bus_dma_segment_t seg; 152459014Sroger bus_size_t align; 152559014Sroger int rseg; 152659014Sroger caddr_t kva; 152759014Sroger 152859014Sroger /* 152959014Sroger * Allocate a DMA area 153059014Sroger */ 153159014Sroger align = 1 << 24; 153259014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 153359014Sroger &rseg, BUS_DMA_NOWAIT)) { 153459014Sroger align = PAGE_SIZE; 153559014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 153659014Sroger &rseg, BUS_DMA_NOWAIT)) { 153762112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 153862112Sroger bktr_name(bktr), size); 153959014Sroger return 0; 154059014Sroger } 154159014Sroger } 154259014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 154359014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 154462112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 154562112Sroger bktr_name(bktr), size); 154659014Sroger bus_dmamem_free(dmat, &seg, rseg); 154759014Sroger return 0; 154859014Sroger } 154959014Sroger#ifdef __OpenBSD__ 155059014Sroger bktr->dm_mapsize = size; 155159014Sroger#endif 155259014Sroger /* 155359014Sroger * Create and locd the DMA map for the DMA area 155459014Sroger */ 155559014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 155662112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 155762112Sroger bktr_name(bktr), size); 155859014Sroger bus_dmamem_unmap(dmat, kva, size); 155959014Sroger bus_dmamem_free(dmat, &seg, rseg); 156059014Sroger return 0; 156159014Sroger } 156259014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 156362112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 156462112Sroger bktr_name(bktr), size); 156559014Sroger bus_dmamem_unmap(dmat, kva, size); 156659014Sroger bus_dmamem_free(dmat, &seg, rseg); 156759014Sroger bus_dmamap_destroy(dmat, *dmapp); 156859014Sroger return 0; 156959014Sroger } 157059014Sroger return (vm_offset_t)kva; 157159014Sroger} 157259014Sroger 157359014Srogervoid 157459014Srogerfree_bktr_mem(bktr, dmap, kva) 157559014Sroger bktr_ptr_t bktr; 157659014Sroger bus_dmamap_t dmap; 157759014Sroger vm_offset_t kva; 157859014Sroger{ 157959014Sroger bus_dma_tag_t dmat = bktr->dmat; 158059014Sroger 158159014Sroger#ifdef __NetBSD__ 158259014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 158359014Sroger#else 158459014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 158559014Sroger#endif 158659014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 158759014Sroger bus_dmamap_destroy(dmat, dmap); 158859014Sroger} 158959014Sroger 159059014Sroger 159159014Sroger/*--------------------------------------------------------- 159259014Sroger** 159359014Sroger** BrookTree 848 character device driver routines 159459014Sroger** 159559014Sroger**--------------------------------------------------------- 159659014Sroger*/ 159759014Sroger 159859014Sroger 159959014Sroger#define VIDEO_DEV 0x00 160059014Sroger#define TUNER_DEV 0x01 160159014Sroger#define VBI_DEV 0x02 160259014Sroger 160362112Sroger#define UNIT(x) (minor((x) & 0x0f)) 160462112Sroger#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 160559014Sroger 160659014Sroger/* 160759014Sroger * 160859014Sroger */ 160959014Srogerint 161083366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 161159014Sroger{ 161259014Sroger bktr_ptr_t bktr; 161359014Sroger int unit; 161459014Sroger 161562112Sroger unit = UNIT(dev); 161659014Sroger 161759014Sroger /* unit out of range */ 161859014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 161962112Sroger return(ENXIO); 162059014Sroger 162159014Sroger bktr = bktr_cd.cd_devs[unit]; 162259014Sroger 162359014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 162462112Sroger return(ENXIO); 162559014Sroger 162662112Sroger switch (FUNCTION(dev)) { 162759014Sroger case VIDEO_DEV: 162862112Sroger return(video_open(bktr)); 162959014Sroger case TUNER_DEV: 163062112Sroger return(tuner_open(bktr)); 163159014Sroger case VBI_DEV: 163262112Sroger return(vbi_open(bktr)); 163359014Sroger } 163459014Sroger 163562112Sroger return(ENXIO); 163659014Sroger} 163759014Sroger 163859014Sroger 163959014Sroger/* 164059014Sroger * 164159014Sroger */ 164259014Srogerint 164383366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 164459014Sroger{ 164559014Sroger bktr_ptr_t bktr; 164659014Sroger int unit; 164759014Sroger 164862112Sroger unit = UNIT(dev); 164959014Sroger 165059014Sroger bktr = bktr_cd.cd_devs[unit]; 165159014Sroger 165262112Sroger switch (FUNCTION(dev)) { 165359014Sroger case VIDEO_DEV: 165462112Sroger return(video_close(bktr)); 165559014Sroger case TUNER_DEV: 165662112Sroger return(tuner_close(bktr)); 165759014Sroger case VBI_DEV: 165862112Sroger return(vbi_close(bktr)); 165959014Sroger } 166059014Sroger 166162112Sroger return(ENXIO); 166259014Sroger} 166359014Sroger 166459014Sroger/* 166559014Sroger * 166659014Sroger */ 166759014Srogerint 166862112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 166959014Sroger{ 167059014Sroger bktr_ptr_t bktr; 167159014Sroger int unit; 167259014Sroger 167362112Sroger unit = UNIT(dev); 167459014Sroger 167559014Sroger bktr = bktr_cd.cd_devs[unit]; 167659014Sroger 167762112Sroger switch (FUNCTION(dev)) { 167859014Sroger case VIDEO_DEV: 167962112Sroger return(video_read(bktr, unit, dev, uio)); 168059014Sroger case VBI_DEV: 168162112Sroger return(vbi_read(bktr, uio, ioflag)); 168259014Sroger } 168359014Sroger 168462112Sroger return(ENXIO); 168559014Sroger} 168659014Sroger 168759014Sroger 168859014Sroger/* 168959014Sroger * 169059014Sroger */ 169159014Srogerint 169262112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 169359014Sroger{ 169459014Sroger /* operation not supported */ 169562112Sroger return(EOPNOTSUPP); 169659014Sroger} 169759014Sroger 169859014Sroger/* 169959014Sroger * 170059014Sroger */ 170159014Srogerint 170283366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 170359014Sroger{ 170459014Sroger bktr_ptr_t bktr; 170559014Sroger int unit; 170659014Sroger 170762112Sroger unit = UNIT(dev); 170859014Sroger 170959014Sroger bktr = bktr_cd.cd_devs[unit]; 171059014Sroger 171159014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 171262112Sroger return(ENOMEM); 171359014Sroger 171462112Sroger switch (FUNCTION(dev)) { 171559014Sroger case VIDEO_DEV: 171662112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 171759014Sroger case TUNER_DEV: 171862112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 171959014Sroger } 172059014Sroger 172162112Sroger return(ENXIO); 172259014Sroger} 172359014Sroger 172459014Sroger/* 172559014Sroger * 172659014Sroger */ 172762214Srogerpaddr_t 172862214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 172959014Sroger{ 173059014Sroger int unit; 173159014Sroger bktr_ptr_t bktr; 173259014Sroger 173362112Sroger unit = UNIT(dev); 173459014Sroger 173562112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 173662112Sroger return(-1); 173759014Sroger 173859014Sroger bktr = bktr_cd.cd_devs[unit]; 173959014Sroger 174062112Sroger if ((vaddr_t)offset < 0) 174162112Sroger return(-1); 174259014Sroger 174362112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 174462112Sroger return(-1); 174559014Sroger 174659014Sroger#ifdef __NetBSD__ 174759014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 174862112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 174959014Sroger#else 175062112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 175159014Sroger#endif 175259014Sroger} 175359014Sroger 175451694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1755