bktr_os.c revision 129879
1119418Sobrien/*- 251694Sroger * 1. Redistributions of source code must retain the 351694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 451694Sroger * All rights reserved. 551694Sroger * 651694Sroger * Redistribution and use in source and binary forms, with or without 751694Sroger * modification, are permitted provided that the following conditions 851694Sroger * are met: 951694Sroger * 1. Redistributions of source code must retain the above copyright 1051694Sroger * notice, this list of conditions and the following disclaimer. 1151694Sroger * 2. Redistributions in binary form must reproduce the above copyright 1251694Sroger * notice, this list of conditions and the following disclaimer in the 1351694Sroger * documentation and/or other materials provided with the distribution. 1451694Sroger * 3. All advertising materials mentioning features or use of this software 1551694Sroger * must display the following acknowledgement: 1651694Sroger * This product includes software developed by Amancio Hasty and 1751694Sroger * Roger Hardiman 1851694Sroger * 4. The name of the author may not be used to endorse or promote products 1951694Sroger * derived from this software without specific prior written permission. 2051694Sroger * 2151694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2251694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2351694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2451694Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2551694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2651694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2751694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2851694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2951694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3051694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3151694Sroger * POSSIBILITY OF SUCH DAMAGE. 3251694Sroger */ 3351694Sroger 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_os.c 129879 2004-05-30 20:08:47Z phk $"); 3651694Sroger 37119418Sobrien/* 38119418Sobrien * This is part of the Driver for Video Capture Cards (Frame grabbers) 39119418Sobrien * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 40119418Sobrien * chipset. 41119418Sobrien * Copyright Roger Hardiman and Amancio Hasty. 42119418Sobrien * 43119418Sobrien * bktr_os : This has all the Operating System dependant code, 44119418Sobrien * probe/attach and open/close/ioctl/read/mmap 45119418Sobrien * memory allocation 46119418Sobrien * PCI bus interfacing 47119418Sobrien */ 48119418Sobrien 4959014Sroger#include "opt_bktr.h" /* include any kernel config options */ 5051694Sroger 5151694Sroger#define FIFO_RISC_DISABLED 0 5251694Sroger#define ALL_INTS_DISABLED 0 5351694Sroger 5462214Sroger 5562214Sroger/*******************/ 5662214Sroger/* *** FreeBSD *** */ 5762214Sroger/*******************/ 5862214Sroger#ifdef __FreeBSD__ 5962214Sroger 6051694Sroger#include <sys/param.h> 6151694Sroger#include <sys/systm.h> 6251694Sroger#include <sys/conf.h> 6351694Sroger#include <sys/uio.h> 6451694Sroger#include <sys/kernel.h> 65129879Sphk#include <sys/module.h> 6651694Sroger#include <sys/signalvar.h> 67124507Salc#include <sys/malloc.h> 6851694Sroger#include <sys/mman.h> 6951694Sroger#include <sys/poll.h> 7070834Swollman#if __FreeBSD_version >= 500014 7170834Swollman#include <sys/selinfo.h> 7270834Swollman#else 7351694Sroger#include <sys/select.h> 7470834Swollman#endif 7551694Sroger#include <sys/vnode.h> 7651694Sroger 7751694Sroger#include <vm/vm.h> 7851694Sroger#include <vm/vm_kern.h> 7951694Sroger#include <vm/pmap.h> 8051694Sroger#include <vm/vm_extern.h> 8151694Sroger 8293023Snsouch#if (__FreeBSD_version >=400000) 8351694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 8451694Sroger#endif 8551694Sroger 8659014Sroger#if (__FreeBSD_version >=300000) 8759014Sroger#include <machine/bus_memio.h> /* used by bus space */ 8859014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 8959014Sroger#include <sys/bus.h> 9059014Sroger#endif 9159014Sroger 9251694Sroger#if (__FreeBSD_version >=400000) 9351694Sroger#include <sys/rman.h> /* used by newbus */ 9451694Sroger#include <machine/resource.h> /* used by newbus */ 9551694Sroger#endif 9651694Sroger 9767306Sroger#if (__FreeBSD_version < 500000) 9867306Sroger#include <machine/clock.h> /* for DELAY */ 9951694Sroger#include <pci/pcivar.h> 10051694Sroger#include <pci/pcireg.h> 101119277Simp#else 102119277Simp#include <dev/pci/pcivar.h> 103119277Simp#include <dev/pci/pcireg.h> 104119277Simp#endif 10551694Sroger 10651694Sroger#include <sys/sysctl.h> 10751694Srogerint bt848_card = -1; 10851694Srogerint bt848_tuner = -1; 10951694Srogerint bt848_reverse_mute = -1; 11051694Srogerint bt848_format = -1; 11159014Srogerint bt848_slow_msp_audio = -1; 112118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 113118819Salexint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 114118819Salexint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 115118819Salex the autoscan seems work well only with FM... */ 116118819Salexint bt848_dolby = 0; 117118819Salex#endif 11851694Sroger 11951694SrogerSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 12051694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 12151694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 12251694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 12351694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 12459014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 125118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 126118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 127118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 128118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 129118819Salex#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 */ 190123291Sobrien#include <dev/bktr/ioctl_meteor.h> 191123291Sobrien#include <dev/bktr/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> 19893023Snsouch 19965692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 20065392Speter#include <dev/bktr/bktr_i2c.h> 20193023Snsouch 20293023Snsouch#include "iicbb_if.h" 20393023Snsouch#include "smbus_if.h" 20462214Sroger#endif 20565392Speter#endif 20651694Sroger 20762214Sroger 20851694Sroger/****************************/ 20951694Sroger/* *** FreeBSD 4.x code *** */ 21051694Sroger/****************************/ 21151694Sroger#if (__FreeBSD_version >= 400000) 21251694Sroger 21351694Srogerstatic int bktr_probe( device_t dev ); 21451694Srogerstatic int bktr_attach( device_t dev ); 21551694Srogerstatic int bktr_detach( device_t dev ); 21651694Srogerstatic int bktr_shutdown( device_t dev ); 21751694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21851694Sroger 21951694Srogerstatic device_method_t bktr_methods[] = { 22051694Sroger /* Device interface */ 22151694Sroger DEVMETHOD(device_probe, bktr_probe), 22251694Sroger DEVMETHOD(device_attach, bktr_attach), 22351694Sroger DEVMETHOD(device_detach, bktr_detach), 22451694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 22551694Sroger 22693023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 22793023Snsouch /* iicbb interface */ 22893023Snsouch DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22993023Snsouch DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 23093023Snsouch DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 23193023Snsouch DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 23293023Snsouch DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 23393023Snsouch DEVMETHOD(iicbb_reset, bti2c_iic_reset), 23493023Snsouch 23593023Snsouch /* smbus interface */ 23693023Snsouch DEVMETHOD(smbus_callback, bti2c_smb_callback), 23793023Snsouch DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 23893023Snsouch DEVMETHOD(smbus_writew, bti2c_smb_writew), 23993023Snsouch DEVMETHOD(smbus_readb, bti2c_smb_readb), 24093023Snsouch#endif 24193023Snsouch 24251694Sroger { 0, 0 } 24351694Sroger}; 24451694Sroger 24551694Srogerstatic driver_t bktr_driver = { 24651694Sroger "bktr", 24751694Sroger bktr_methods, 24851694Sroger sizeof(struct bktr_softc), 24951694Sroger}; 25051694Sroger 25151694Srogerstatic devclass_t bktr_devclass; 25251694Sroger 25351694Srogerstatic d_open_t bktr_open; 25451694Srogerstatic d_close_t bktr_close; 25551694Srogerstatic d_read_t bktr_read; 25651694Srogerstatic d_write_t bktr_write; 25751694Srogerstatic d_ioctl_t bktr_ioctl; 25851694Srogerstatic d_mmap_t bktr_mmap; 25951694Srogerstatic d_poll_t bktr_poll; 26051694Sroger 26151694Srogerstatic struct cdevsw bktr_cdevsw = { 262126080Sphk .d_version = D_VERSION, 263126080Sphk .d_flags = D_NEEDGIANT, 264111815Sphk .d_open = bktr_open, 265111815Sphk .d_close = bktr_close, 266111815Sphk .d_read = bktr_read, 267111815Sphk .d_write = bktr_write, 268111815Sphk .d_ioctl = bktr_ioctl, 269111815Sphk .d_poll = bktr_poll, 270111815Sphk .d_mmap = bktr_mmap, 271111815Sphk .d_name = "bktr", 27251694Sroger}; 27351694Sroger 27452995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 27567306Sroger#if (__FreeBSD_version > 410000) 27665728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27765728SrogerMODULE_VERSION(bktr, 1); 27867306Sroger#endif 27951694Sroger 28051694Sroger 28151694Sroger/* 28251694Sroger * the boot time probe routine. 28351694Sroger */ 28451694Srogerstatic int 28551694Srogerbktr_probe( device_t dev ) 28651694Sroger{ 28751694Sroger unsigned int type = pci_get_devid(dev); 28851694Sroger unsigned int rev = pci_get_revid(dev); 28951694Sroger 29067306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 29167306Sroger { 29267306Sroger switch (PCI_PRODUCT(type)) { 29367306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 29467306Sroger if (rev == 0x12) 29567306Sroger device_set_desc(dev, "BrookTree 848A"); 29667306Sroger else 29767306Sroger device_set_desc(dev, "BrookTree 848"); 29867306Sroger return 0; 29967306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 30067306Sroger device_set_desc(dev, "BrookTree 849A"); 30167306Sroger return 0; 30267306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 30367306Sroger device_set_desc(dev, "BrookTree 878"); 30467306Sroger return 0; 30567306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 30667306Sroger device_set_desc(dev, "BrookTree 879"); 30767306Sroger return 0; 30867306Sroger } 30951694Sroger }; 31051694Sroger 31151694Sroger return ENXIO; 31251694Sroger} 31351694Sroger 31451694Sroger 31551694Sroger/* 31651694Sroger * the attach routine. 31751694Sroger */ 31851694Srogerstatic int 31951694Srogerbktr_attach( device_t dev ) 32051694Sroger{ 32151694Sroger u_long latency; 32251694Sroger u_long fun; 32351694Sroger u_long val; 32451694Sroger unsigned int rev; 32551694Sroger unsigned int unit; 32651694Sroger int error = 0; 32751694Sroger#ifdef BROOKTREE_IRQ 32851694Sroger u_long old_irq, new_irq; 32951694Sroger#endif 33051694Sroger 33151694Sroger struct bktr_softc *bktr = device_get_softc(dev); 33251694Sroger 33351694Sroger unit = device_get_unit(dev); 33451694Sroger 33562112Sroger /* build the device name for bktr_name() */ 33662112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 33762112Sroger 33851694Sroger /* 33951694Sroger * Enable bus mastering and Memory Mapped device 34051694Sroger */ 34151694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 34251694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 34351694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 34451694Sroger 34551694Sroger /* 34651694Sroger * Map control/status registers. 34751694Sroger */ 348119690Sjhb bktr->mem_rid = PCIR_BAR(0); 349127135Snjl bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 350127135Snjl &bktr->mem_rid, RF_ACTIVE); 35151694Sroger 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; 380127135Snjl bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 381127135Snjl &bktr->irq_rid, 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{ 48651694Sroger struct bktr_softc *bktr = device_get_softc(dev); 48751694Sroger 488118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 489118819Salex /* Disable the soundchip and kernel thread */ 490118819Salex if (bktr->msp3400c_info != NULL) 491118819Salex msp_detach(bktr); 492118819Salex#endif 493118819Salex 49451694Sroger /* Disable the brooktree device */ 49559014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 49659014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49751694Sroger 49893023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 49993023Snsouch if (bt848_i2c_detach(dev)) 500115556Sphk printf("bktr%d: i2c_attach: can't attach\n", 501115556Sphk device_get_unit(dev)); 50293023Snsouch#endif 503123088Struckman#ifdef USE_VBIMUTEX 504123088Struckman mtx_destroy(&bktr->vbimutex); 505123088Struckman#endif 50693023Snsouch 50767306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50867306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 50967306Sroger /* then reload the main bktr driver module */ 51051694Sroger 511107699Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices, 512107699Sroger * the aliases for unit 0 are automatically destroyed */ 51367306Sroger destroy_dev(bktr->vbidev); 51467306Sroger destroy_dev(bktr->tunerdev); 51567306Sroger destroy_dev(bktr->bktrdev); 51667306Sroger 51751694Sroger /* 51851694Sroger * Deallocate resources. 51951694Sroger */ 52051694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 52165049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 52265049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 52365049Sroger 52451694Sroger return 0; 52551694Sroger} 52651694Sroger 52751694Sroger/* 52851694Sroger * the shutdown routine. 52951694Sroger */ 53051694Srogerstatic int 53151694Srogerbktr_shutdown( device_t dev ) 53251694Sroger{ 53351694Sroger struct bktr_softc *bktr = device_get_softc(dev); 53451694Sroger 53551694Sroger /* Disable the brooktree device */ 53659014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53759014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 53851694Sroger 53951694Sroger return 0; 54051694Sroger} 54151694Sroger 54251694Sroger 54351694Sroger/* 54451694Sroger * Special Memory Allocation 54551694Sroger */ 54651694Srogervm_offset_t 54751694Srogerget_bktr_mem( int unit, unsigned size ) 54851694Sroger{ 54951694Sroger vm_offset_t addr = 0; 55051694Sroger 551124507Salc addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 552124507Salc 0xffffffff, 1<<24, 0); 55351694Sroger if (addr == 0) 554124507Salc addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 555124507Salc 0xffffffff, PAGE_SIZE, 0); 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 */ 582104094Sphkstatic int 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 637118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 638118819Salex if (bt848_stereo_once != 0) { 639118819Salex if ((bt848_stereo_once >> 8) == unit ) { 640118819Salex bktr->stereo_once = (bt848_stereo_once & 0xff); 641118819Salex } 642118819Salex } 643118819Salex 644118819Salex if (bt848_amsound != -1) { 645118819Salex if ((bt848_amsound >> 8) == unit ) { 646118819Salex bktr->amsound = (bt848_amsound & 0xff); 647118819Salex } 648118819Salex } 649118819Salex 650118819Salex if (bt848_dolby != -1) { 651118819Salex if ((bt848_dolby >> 8) == unit ) { 652118819Salex bktr->dolby = (bt848_dolby & 0xff); 653118819Salex } 654118819Salex } 655118819Salex#endif 656118819Salex 65751694Sroger switch ( FUNCTION( minor(dev) ) ) { 65851694Sroger case VIDEO_DEV: 65951694Sroger result = video_open( bktr ); 66051694Sroger break; 66151694Sroger case TUNER_DEV: 66251694Sroger result = tuner_open( bktr ); 66351694Sroger break; 66451694Sroger case VBI_DEV: 66551694Sroger result = vbi_open( bktr ); 66651694Sroger break; 66751694Sroger default: 66851694Sroger result = ENXIO; 66951694Sroger break; 67051694Sroger } 67151694Sroger 67251694Sroger /* If there was an error opening the device, undo the busy status */ 67351694Sroger if (result != 0) 67451694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 67551694Sroger return( result ); 67651694Sroger} 67751694Sroger 67851694Sroger 67951694Sroger/* 68051694Sroger * 68151694Sroger */ 682104094Sphkstatic int 68383366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 68451694Sroger{ 68551694Sroger bktr_ptr_t bktr; 68651694Sroger int unit; 68751694Sroger int result; 68851694Sroger 68951694Sroger unit = UNIT( minor(dev) ); 69051694Sroger 69151694Sroger /* Get the device data */ 69251694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 69351694Sroger if (bktr == NULL) { 69451694Sroger /* the device is no longer valid/functioning */ 69551694Sroger return (ENXIO); 69651694Sroger } 69751694Sroger 69851694Sroger switch ( FUNCTION( minor(dev) ) ) { 69951694Sroger case VIDEO_DEV: 70051694Sroger result = video_close( bktr ); 70151694Sroger break; 70251694Sroger case TUNER_DEV: 70351694Sroger result = tuner_close( bktr ); 70451694Sroger break; 70551694Sroger case VBI_DEV: 70651694Sroger result = vbi_close( bktr ); 70751694Sroger break; 70851694Sroger default: 70951694Sroger return (ENXIO); 71051694Sroger break; 71151694Sroger } 71251694Sroger 71351694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 71451694Sroger return( result ); 71551694Sroger} 71651694Sroger 71751694Sroger 71851694Sroger/* 71951694Sroger * 72051694Sroger */ 721104094Sphkstatic int 72251694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 72351694Sroger{ 72451694Sroger bktr_ptr_t bktr; 72551694Sroger int unit; 72651694Sroger 72751694Sroger unit = UNIT(minor(dev)); 72851694Sroger 72951694Sroger /* Get the device data */ 73051694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 73151694Sroger if (bktr == NULL) { 73251694Sroger /* the device is no longer valid/functioning */ 73351694Sroger return (ENXIO); 73451694Sroger } 73551694Sroger 73651694Sroger switch ( FUNCTION( minor(dev) ) ) { 73751694Sroger case VIDEO_DEV: 73851694Sroger return( video_read( bktr, unit, dev, uio ) ); 73951694Sroger case VBI_DEV: 74051694Sroger return( vbi_read( bktr, uio, ioflag ) ); 74151694Sroger } 74251694Sroger return( ENXIO ); 74351694Sroger} 74451694Sroger 74551694Sroger 74651694Sroger/* 74751694Sroger * 74851694Sroger */ 749104094Sphkstatic int 75051694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 75151694Sroger{ 75251694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 75351694Sroger} 75451694Sroger 75551694Sroger 75651694Sroger/* 75751694Sroger * 75851694Sroger */ 759104094Sphkstatic int 76083366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 76151694Sroger{ 76251694Sroger bktr_ptr_t bktr; 76351694Sroger int unit; 76451694Sroger 76551694Sroger unit = UNIT(minor(dev)); 76651694Sroger 76751694Sroger /* Get the device data */ 76851694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76951694Sroger if (bktr == NULL) { 77051694Sroger /* the device is no longer valid/functioning */ 77151694Sroger return (ENXIO); 77251694Sroger } 77351694Sroger 77451694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 77551694Sroger return( ENOMEM ); 77651694Sroger 77751694Sroger switch ( FUNCTION( minor(dev) ) ) { 77851694Sroger case VIDEO_DEV: 77983366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 78051694Sroger case TUNER_DEV: 78183366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 78251694Sroger } 78351694Sroger 78451694Sroger return( ENXIO ); 78551694Sroger} 78651694Sroger 78751694Sroger 78851694Sroger/* 78951694Sroger * 79051694Sroger */ 791104094Sphkstatic int 792112569Sjakebktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 79351694Sroger{ 79451694Sroger int unit; 79551694Sroger bktr_ptr_t bktr; 79651694Sroger 79751694Sroger unit = UNIT(minor(dev)); 79851694Sroger 79951694Sroger if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 80051694Sroger return( -1 ); 80151694Sroger 80251694Sroger /* Get the device data */ 80351694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 80451694Sroger if (bktr == NULL) { 80551694Sroger /* the device is no longer valid/functioning */ 80651694Sroger return (ENXIO); 80751694Sroger } 80851694Sroger 80951694Sroger if (nprot & PROT_EXEC) 81051694Sroger return( -1 ); 81151694Sroger 81251694Sroger if (offset < 0) 81351694Sroger return( -1 ); 81451694Sroger 81551694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 81651694Sroger return( -1 ); 81751694Sroger 818111462Smux *paddr = vtophys(bktr->bigbuf) + offset; 819111462Smux return( 0 ); 82051694Sroger} 82151694Sroger 822104094Sphkstatic int 823104094Sphkbktr_poll( dev_t dev, int events, struct thread *td) 82451694Sroger{ 82551694Sroger int unit; 82651694Sroger bktr_ptr_t bktr; 82751694Sroger int revents = 0; 82859277Sroger DECLARE_INTR_MASK(s); 82951694Sroger 83051694Sroger unit = UNIT(minor(dev)); 83151694Sroger 83251694Sroger /* Get the device data */ 83351694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 83451694Sroger if (bktr == NULL) { 83551694Sroger /* the device is no longer valid/functioning */ 83651694Sroger return (ENXIO); 83751694Sroger } 83851694Sroger 839123088Struckman LOCK_VBI(bktr); 84059277Sroger DISABLE_INTR(s); 84151694Sroger 84251694Sroger if (events & (POLLIN | POLLRDNORM)) { 84351694Sroger 84451694Sroger switch ( FUNCTION( minor(dev) ) ) { 84551694Sroger case VBI_DEV: 84651694Sroger if(bktr->vbisize == 0) 84783366Sjulian selrecord(td, &bktr->vbi_select); 84851694Sroger else 84951694Sroger revents |= events & (POLLIN | POLLRDNORM); 85051694Sroger break; 85151694Sroger } 85251694Sroger } 85351694Sroger 85459250Sroger ENABLE_INTR(s); 855123088Struckman UNLOCK_VBI(bktr); 85651694Sroger 85751694Sroger return (revents); 85851694Sroger} 85951694Sroger 86051694Sroger#endif /* FreeBSD 4.x specific kernel interface routines */ 86151694Sroger 86251694Sroger/*****************/ 86351694Sroger/* *** BSDI *** */ 86451694Sroger/*****************/ 86551694Sroger 86651694Sroger#if defined(__bsdi__) 86751694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 86851694Sroger 86951694Sroger 87051694Sroger/*****************************/ 87151694Sroger/* *** OpenBSD / NetBSD *** */ 87251694Sroger/*****************************/ 87351694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 87459014Sroger 87559014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 87659014Sroger 87759014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 87859014Sroger 87959014Sroger#define bktr_open bktropen 88059014Sroger#define bktr_close bktrclose 88159014Sroger#define bktr_read bktrread 88259014Sroger#define bktr_write bktrwrite 88359014Sroger#define bktr_ioctl bktrioctl 88459014Sroger#define bktr_mmap bktrmmap 88559014Sroger 88659014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 88759014Sroger vm_offset_t, vm_offset_t); 88859014Sroger 88962112Sroger#if defined(__OpenBSD__) 89092739Salfredstatic int bktr_probe(struct device *, void *, void *); 89159014Sroger#else 89292739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 89359014Sroger#endif 89492739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 89559014Sroger 89659014Srogerstruct cfattach bktr_ca = { 89759014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 89859014Sroger}; 89959014Sroger 90059014Sroger#if defined(__NetBSD__) 90159014Srogerextern struct cfdriver bktr_cd; 90259014Sroger#else 90359014Srogerstruct cfdriver bktr_cd = { 90459014Sroger NULL, "bktr", DV_DULL 90559014Sroger}; 90659014Sroger#endif 90759014Sroger 90862112Srogerint 90962112Srogerbktr_probe(parent, match, aux) 91062112Sroger struct device *parent; 91162112Sroger#if defined(__OpenBSD__) 91259014Sroger void *match; 91359014Sroger#else 91459014Sroger struct cfdata *match; 91559014Sroger#endif 91659014Sroger void *aux; 91759014Sroger{ 91859014Sroger struct pci_attach_args *pa = aux; 91959014Sroger 92059014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 92159014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 92259014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 92359014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 92459014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 92559014Sroger return 1; 92659014Sroger 92759014Sroger return 0; 92859014Sroger} 92959014Sroger 93059014Sroger 93159014Sroger/* 93259014Sroger * the attach routine. 93359014Sroger */ 93459014Srogerstatic void 93562112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 93659014Sroger{ 93759014Sroger bktr_ptr_t bktr; 93859014Sroger u_long latency; 93959014Sroger u_long fun; 94059014Sroger unsigned int rev; 94159014Sroger 94259014Sroger#if defined(__OpenBSD__) 94359014Sroger struct pci_attach_args *pa = aux; 94459014Sroger pci_chipset_tag_t pc = pa->pa_pc; 94559014Sroger 94659014Sroger pci_intr_handle_t ih; 94759014Sroger const char *intrstr; 94859014Sroger int retval; 94959014Sroger int unit; 95059014Sroger 95159014Sroger bktr = (bktr_ptr_t)self; 95259014Sroger unit = bktr->bktr_dev.dv_unit; 95359014Sroger 95459014Sroger bktr->pc = pa->pa_pc; 95559014Sroger bktr->tag = pa->pa_tag; 95659014Sroger bktr->dmat = pa->pa_dmat; 95759014Sroger 95859014Sroger /* 95959014Sroger * map memory 96059014Sroger */ 96159014Sroger bktr->memt = pa->pa_memt; 96259014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 96359014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 96459014Sroger if (!retval) 96559014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 96659014Sroger bktr->obmemsz, 0, &bktr->memh); 96759014Sroger if (retval) { 96859014Sroger printf(": couldn't map memory\n"); 96959014Sroger return; 97059014Sroger } 97159014Sroger 97259014Sroger 97359014Sroger /* 97459014Sroger * map interrupt 97559014Sroger */ 97659014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 97759014Sroger pa->pa_intrline, &ih)) { 97859014Sroger printf(": couldn't map interrupt\n"); 97959014Sroger return; 98059014Sroger } 98159014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 98259014Sroger 98359014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 98459014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 98559014Sroger if (bktr->ih == NULL) { 98659014Sroger printf(": couldn't establish interrupt"); 98759014Sroger if (intrstr != NULL) 98859014Sroger printf(" at %s", intrstr); 98959014Sroger printf("\n"); 99059014Sroger return; 99159014Sroger } 99259014Sroger 99359014Sroger if (intrstr != NULL) 99459014Sroger printf(": %s\n", intrstr); 99559014Sroger#endif /* __OpenBSD__ */ 99659014Sroger 99759014Sroger#if defined(__NetBSD__) 99859014Sroger struct pci_attach_args *pa = aux; 99959014Sroger pci_intr_handle_t ih; 100059014Sroger const char *intrstr; 100159014Sroger int retval; 100259014Sroger int unit; 100359014Sroger 100459014Sroger bktr = (bktr_ptr_t)self; 100559014Sroger unit = bktr->bktr_dev.dv_unit; 100659014Sroger bktr->dmat = pa->pa_dmat; 100759014Sroger 100859014Sroger printf("\n"); 100959014Sroger 101059014Sroger /* 101159014Sroger * map memory 101259014Sroger */ 101359014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 101462112Sroger PCI_MAPREG_TYPE_MEM 101562112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 101662112Sroger &bktr->memt, &bktr->memh, NULL, 101762112Sroger &bktr->obmemsz); 101862112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 101962112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 102059014Sroger if (retval) { 102162112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 102259014Sroger return; 102359014Sroger } 102459014Sroger 102559014Sroger /* 102659014Sroger * Disable the brooktree device 102759014Sroger */ 102859014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 102959014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 103059014Sroger 103159014Sroger /* 103259014Sroger * map interrupt 103359014Sroger */ 103459014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 103559014Sroger pa->pa_intrline, &ih)) { 103662112Sroger printf("%s: couldn't map interrupt\n", 103762112Sroger bktr_name(bktr)); 103859014Sroger return; 103959014Sroger } 104059014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 104159014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 104259014Sroger bktr_intr, bktr); 104359014Sroger if (bktr->ih == NULL) { 104459014Sroger printf("%s: couldn't establish interrupt", 104562112Sroger bktr_name(bktr)); 104662112Sroger if (intrstr != NULL) 104762112Sroger printf(" at %s", intrstr); 104862112Sroger printf("\n"); 104962112Sroger return; 105059014Sroger } 105159014Sroger if (intrstr != NULL) 105262112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 105359014Sroger intrstr); 105459014Sroger#endif /* __NetBSD__ */ 105559014Sroger 105659014Sroger/* 105759014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 105859014Sroger * you have more than four, then 16 would probably be a better value. 105959014Sroger */ 106059014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 106159014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 106259014Sroger#endif 106359014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 106459014Sroger latency = (latency >> 8) & 0xff; 106559014Sroger 106662112Sroger if (!latency) { 106762112Sroger if (bootverbose) { 106859014Sroger printf("%s: PCI bus latency was 0 changing to %d", 106962112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 107059014Sroger } 107159014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 107259014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 107359014Sroger PCI_LATENCY_TIMER, latency<<8); 107459014Sroger } 107559014Sroger 107659014Sroger 107762112Sroger /* Enabled Bus Master 107862112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 107962112Sroger boot) */ 108059014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 108162112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 108262112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 108359014Sroger 108459014Sroger /* read the pci id and determine the card type */ 108559014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 108659014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 108759014Sroger 108862112Sroger common_bktr_attach(bktr, unit, fun, rev); 108959014Sroger} 109059014Sroger 109159014Sroger 109259014Sroger/* 109359014Sroger * Special Memory Allocation 109459014Sroger */ 109559014Srogervm_offset_t 109659014Srogerget_bktr_mem(bktr, dmapp, size) 109759014Sroger bktr_ptr_t bktr; 109859014Sroger bus_dmamap_t *dmapp; 109959014Sroger unsigned int size; 110059014Sroger{ 110159014Sroger bus_dma_tag_t dmat = bktr->dmat; 110259014Sroger bus_dma_segment_t seg; 110359014Sroger bus_size_t align; 110459014Sroger int rseg; 110559014Sroger caddr_t kva; 110659014Sroger 110759014Sroger /* 110859014Sroger * Allocate a DMA area 110959014Sroger */ 111059014Sroger align = 1 << 24; 111159014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111259014Sroger &rseg, BUS_DMA_NOWAIT)) { 111359014Sroger align = PAGE_SIZE; 111459014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111559014Sroger &rseg, BUS_DMA_NOWAIT)) { 111662112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 111762112Sroger bktr_name(bktr), size); 111859014Sroger return 0; 111959014Sroger } 112059014Sroger } 112159014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 112259014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 112362112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 112462112Sroger bktr_name(bktr), size); 112559014Sroger bus_dmamem_free(dmat, &seg, rseg); 112659014Sroger return 0; 112759014Sroger } 112859014Sroger#ifdef __OpenBSD__ 112959014Sroger bktr->dm_mapsize = size; 113059014Sroger#endif 113159014Sroger /* 113259014Sroger * Create and locd the DMA map for the DMA area 113359014Sroger */ 113459014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 113562112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 113662112Sroger bktr_name(bktr), size); 113759014Sroger bus_dmamem_unmap(dmat, kva, size); 113859014Sroger bus_dmamem_free(dmat, &seg, rseg); 113959014Sroger return 0; 114059014Sroger } 114159014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 114262112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 114362112Sroger bktr_name(bktr), size); 114459014Sroger bus_dmamem_unmap(dmat, kva, size); 114559014Sroger bus_dmamem_free(dmat, &seg, rseg); 114659014Sroger bus_dmamap_destroy(dmat, *dmapp); 114759014Sroger return 0; 114859014Sroger } 114959014Sroger return (vm_offset_t)kva; 115059014Sroger} 115159014Sroger 115259014Srogervoid 115359014Srogerfree_bktr_mem(bktr, dmap, kva) 115459014Sroger bktr_ptr_t bktr; 115559014Sroger bus_dmamap_t dmap; 115659014Sroger vm_offset_t kva; 115759014Sroger{ 115859014Sroger bus_dma_tag_t dmat = bktr->dmat; 115959014Sroger 116059014Sroger#ifdef __NetBSD__ 116159014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 116259014Sroger#else 116359014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 116459014Sroger#endif 116559014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 116659014Sroger bus_dmamap_destroy(dmat, dmap); 116759014Sroger} 116859014Sroger 116959014Sroger 117059014Sroger/*--------------------------------------------------------- 117159014Sroger** 117259014Sroger** BrookTree 848 character device driver routines 117359014Sroger** 117459014Sroger**--------------------------------------------------------- 117559014Sroger*/ 117659014Sroger 117759014Sroger 117859014Sroger#define VIDEO_DEV 0x00 117959014Sroger#define TUNER_DEV 0x01 118059014Sroger#define VBI_DEV 0x02 118159014Sroger 118262112Sroger#define UNIT(x) (minor((x) & 0x0f)) 118362112Sroger#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 118459014Sroger 118559014Sroger/* 118659014Sroger * 118759014Sroger */ 118859014Srogerint 118983366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 119059014Sroger{ 119159014Sroger bktr_ptr_t bktr; 119259014Sroger int unit; 119359014Sroger 119462112Sroger unit = UNIT(dev); 119559014Sroger 119659014Sroger /* unit out of range */ 119759014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 119862112Sroger return(ENXIO); 119959014Sroger 120059014Sroger bktr = bktr_cd.cd_devs[unit]; 120159014Sroger 120259014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 120362112Sroger return(ENXIO); 120459014Sroger 120562112Sroger switch (FUNCTION(dev)) { 120659014Sroger case VIDEO_DEV: 120762112Sroger return(video_open(bktr)); 120859014Sroger case TUNER_DEV: 120962112Sroger return(tuner_open(bktr)); 121059014Sroger case VBI_DEV: 121162112Sroger return(vbi_open(bktr)); 121259014Sroger } 121359014Sroger 121462112Sroger return(ENXIO); 121559014Sroger} 121659014Sroger 121759014Sroger 121859014Sroger/* 121959014Sroger * 122059014Sroger */ 122159014Srogerint 122283366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 122359014Sroger{ 122459014Sroger bktr_ptr_t bktr; 122559014Sroger int unit; 122659014Sroger 122762112Sroger unit = UNIT(dev); 122859014Sroger 122959014Sroger bktr = bktr_cd.cd_devs[unit]; 123059014Sroger 123162112Sroger switch (FUNCTION(dev)) { 123259014Sroger case VIDEO_DEV: 123362112Sroger return(video_close(bktr)); 123459014Sroger case TUNER_DEV: 123562112Sroger return(tuner_close(bktr)); 123659014Sroger case VBI_DEV: 123762112Sroger return(vbi_close(bktr)); 123859014Sroger } 123959014Sroger 124062112Sroger return(ENXIO); 124159014Sroger} 124259014Sroger 124359014Sroger/* 124459014Sroger * 124559014Sroger */ 124659014Srogerint 124762112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 124859014Sroger{ 124959014Sroger bktr_ptr_t bktr; 125059014Sroger int unit; 125159014Sroger 125262112Sroger unit = UNIT(dev); 125359014Sroger 125459014Sroger bktr = bktr_cd.cd_devs[unit]; 125559014Sroger 125662112Sroger switch (FUNCTION(dev)) { 125759014Sroger case VIDEO_DEV: 125862112Sroger return(video_read(bktr, unit, dev, uio)); 125959014Sroger case VBI_DEV: 126062112Sroger return(vbi_read(bktr, uio, ioflag)); 126159014Sroger } 126259014Sroger 126362112Sroger return(ENXIO); 126459014Sroger} 126559014Sroger 126659014Sroger 126759014Sroger/* 126859014Sroger * 126959014Sroger */ 127059014Srogerint 127162112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 127259014Sroger{ 127359014Sroger /* operation not supported */ 127462112Sroger return(EOPNOTSUPP); 127559014Sroger} 127659014Sroger 127759014Sroger/* 127859014Sroger * 127959014Sroger */ 128059014Srogerint 128183366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 128259014Sroger{ 128359014Sroger bktr_ptr_t bktr; 128459014Sroger int unit; 128559014Sroger 128662112Sroger unit = UNIT(dev); 128759014Sroger 128859014Sroger bktr = bktr_cd.cd_devs[unit]; 128959014Sroger 129059014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 129162112Sroger return(ENOMEM); 129259014Sroger 129362112Sroger switch (FUNCTION(dev)) { 129459014Sroger case VIDEO_DEV: 129562112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 129659014Sroger case TUNER_DEV: 129762112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 129859014Sroger } 129959014Sroger 130062112Sroger return(ENXIO); 130159014Sroger} 130259014Sroger 130359014Sroger/* 130459014Sroger * 130559014Sroger */ 130662214Srogerpaddr_t 130762214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 130859014Sroger{ 130959014Sroger int unit; 131059014Sroger bktr_ptr_t bktr; 131159014Sroger 131262112Sroger unit = UNIT(dev); 131359014Sroger 131462112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 131562112Sroger return(-1); 131659014Sroger 131759014Sroger bktr = bktr_cd.cd_devs[unit]; 131859014Sroger 131962112Sroger if ((vaddr_t)offset < 0) 132062112Sroger return(-1); 132159014Sroger 132262112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 132362112Sroger return(-1); 132459014Sroger 132559014Sroger#ifdef __NetBSD__ 132659014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 132762112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 132859014Sroger#else 132962112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 133059014Sroger#endif 133159014Sroger} 133259014Sroger 133351694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1334