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$"); 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 7651694Sroger#include <vm/vm.h> 7751694Sroger#include <vm/vm_kern.h> 7851694Sroger#include <vm/pmap.h> 7951694Sroger#include <vm/vm_extern.h> 8051694Sroger 8151694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 8251694Sroger 8359014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 8459014Sroger#include <sys/bus.h> 8559014Sroger 8651694Sroger#include <sys/rman.h> /* used by newbus */ 8751694Sroger#include <machine/resource.h> /* used by newbus */ 8851694Sroger 8967306Sroger#if (__FreeBSD_version < 500000) 9067306Sroger#include <machine/clock.h> /* for DELAY */ 9151694Sroger#include <pci/pcivar.h> 9251694Sroger#include <pci/pcireg.h> 93119277Simp#else 94119277Simp#include <dev/pci/pcivar.h> 95119277Simp#include <dev/pci/pcireg.h> 96119277Simp#endif 9751694Sroger 9851694Sroger#include <sys/sysctl.h> 9951694Srogerint bt848_card = -1; 10051694Srogerint bt848_tuner = -1; 10151694Srogerint bt848_reverse_mute = -1; 10251694Srogerint bt848_format = -1; 10359014Srogerint bt848_slow_msp_audio = -1; 104118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 105118819Salexint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 106118819Salexint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 107118819Salex the autoscan seems work well only with FM... */ 108118819Salexint bt848_dolby = 0; 109118819Salex#endif 11051694Sroger 111227309Sedstatic SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 11251694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 11351694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 11451694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 11551694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 11659014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 117118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 118118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 119118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 120118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 121118819Salex#endif 12251694Sroger 12362214Sroger#endif /* end freebsd section */ 12451694Sroger 12562214Sroger 12662214Sroger 12751694Sroger/****************/ 12851694Sroger/* *** BSDI *** */ 12951694Sroger/****************/ 13051694Sroger#ifdef __bsdi__ 13151694Sroger#endif /* __bsdi__ */ 13251694Sroger 13351694Sroger 13451694Sroger/**************************/ 13551694Sroger/* *** OpenBSD/NetBSD *** */ 13651694Sroger/**************************/ 13751694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 13862214Sroger 13962214Sroger#include <sys/param.h> 14062214Sroger#include <sys/systm.h> 14162214Sroger#include <sys/conf.h> 14262214Sroger#include <sys/uio.h> 14362214Sroger#include <sys/kernel.h> 14462214Sroger#include <sys/signalvar.h> 14562214Sroger#include <sys/mman.h> 14662214Sroger#include <sys/poll.h> 14762214Sroger#include <sys/select.h> 14862214Sroger#include <sys/vnode.h> 14962214Sroger 15062214Sroger#include <vm/vm.h> 15162214Sroger 152158937Sjmg#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 153158937Sjmg 15462214Sroger#ifndef __NetBSD__ 15562214Sroger#include <vm/vm_kern.h> 15662214Sroger#include <vm/pmap.h> 15762214Sroger#include <vm/vm_extern.h> 15862214Sroger#endif 15962214Sroger 16059014Sroger#include <sys/device.h> 16159014Sroger#include <dev/pci/pcivar.h> 16259014Sroger#include <dev/pci/pcireg.h> 16359014Sroger#include <dev/pci/pcidevs.h> 16459014Sroger 16559014Sroger#define BKTR_DEBUG 16659014Sroger#ifdef BKTR_DEBUG 16759014Srogerint bktr_debug = 0; 16859014Sroger#define DPR(x) (bktr_debug ? printf x : 0) 16959014Sroger#else 17059014Sroger#define DPR(x) 17159014Sroger#endif 17251694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 17351694Sroger 17451694Sroger 17562214Sroger#ifdef __NetBSD__ 17662214Sroger#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 17762214Sroger#include <dev/pci/bktr/bktr_reg.h> 17862214Sroger#include <dev/pci/bktr/bktr_tuner.h> 17962214Sroger#include <dev/pci/bktr/bktr_card.h> 18062214Sroger#include <dev/pci/bktr/bktr_audio.h> 18162214Sroger#include <dev/pci/bktr/bktr_core.h> 18262214Sroger#include <dev/pci/bktr/bktr_os.h> 18362214Sroger#else /* Traditional location for .h files */ 184123291Sobrien#include <dev/bktr/ioctl_meteor.h> 185123291Sobrien#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 18662214Sroger#include <dev/bktr/bktr_reg.h> 18762214Sroger#include <dev/bktr/bktr_tuner.h> 18862214Sroger#include <dev/bktr/bktr_card.h> 18962214Sroger#include <dev/bktr/bktr_audio.h> 19062214Sroger#include <dev/bktr/bktr_core.h> 19162214Sroger#include <dev/bktr/bktr_os.h> 19293023Snsouch 19365692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 19465392Speter#include <dev/bktr/bktr_i2c.h> 19593023Snsouch 19693023Snsouch#include "iicbb_if.h" 19793023Snsouch#include "smbus_if.h" 19862214Sroger#endif 19965392Speter#endif 20051694Sroger 20162214Sroger 20251694Sroger/****************************/ 20351694Sroger/* *** FreeBSD 4.x code *** */ 20451694Sroger/****************************/ 20551694Sroger 20651694Srogerstatic int bktr_probe( device_t dev ); 20751694Srogerstatic int bktr_attach( device_t dev ); 20851694Srogerstatic int bktr_detach( device_t dev ); 20951694Srogerstatic int bktr_shutdown( device_t dev ); 21051694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21151694Sroger 21251694Srogerstatic device_method_t bktr_methods[] = { 21351694Sroger /* Device interface */ 21451694Sroger DEVMETHOD(device_probe, bktr_probe), 21551694Sroger DEVMETHOD(device_attach, bktr_attach), 21651694Sroger DEVMETHOD(device_detach, bktr_detach), 21751694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 21851694Sroger 21993023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 22093023Snsouch /* iicbb interface */ 22193023Snsouch DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22293023Snsouch DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 22393023Snsouch DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 22493023Snsouch DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 22593023Snsouch DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 22693023Snsouch DEVMETHOD(iicbb_reset, bti2c_iic_reset), 22793023Snsouch 22893023Snsouch /* smbus interface */ 22993023Snsouch DEVMETHOD(smbus_callback, bti2c_smb_callback), 23093023Snsouch DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 23193023Snsouch DEVMETHOD(smbus_writew, bti2c_smb_writew), 23293023Snsouch DEVMETHOD(smbus_readb, bti2c_smb_readb), 23393023Snsouch#endif 23493023Snsouch 23551694Sroger { 0, 0 } 23651694Sroger}; 23751694Sroger 23851694Srogerstatic driver_t bktr_driver = { 23951694Sroger "bktr", 24051694Sroger bktr_methods, 24151694Sroger sizeof(struct bktr_softc), 24251694Sroger}; 24351694Sroger 24451694Srogerstatic devclass_t bktr_devclass; 24551694Sroger 24651694Srogerstatic d_open_t bktr_open; 24751694Srogerstatic d_close_t bktr_close; 24851694Srogerstatic d_read_t bktr_read; 24951694Srogerstatic d_write_t bktr_write; 25051694Srogerstatic d_ioctl_t bktr_ioctl; 25151694Srogerstatic d_mmap_t bktr_mmap; 25251694Srogerstatic d_poll_t bktr_poll; 25351694Sroger 25451694Srogerstatic struct cdevsw bktr_cdevsw = { 255126080Sphk .d_version = D_VERSION, 256126080Sphk .d_flags = D_NEEDGIANT, 257111815Sphk .d_open = bktr_open, 258111815Sphk .d_close = bktr_close, 259111815Sphk .d_read = bktr_read, 260111815Sphk .d_write = bktr_write, 261111815Sphk .d_ioctl = bktr_ioctl, 262111815Sphk .d_poll = bktr_poll, 263111815Sphk .d_mmap = bktr_mmap, 264111815Sphk .d_name = "bktr", 26551694Sroger}; 26651694Sroger 267154897Sjmg#ifdef BKTR_USE_FREEBSD_SMBUS 268154897Sjmg#include <dev/iicbus/iiconf.h> 269154897Sjmg#include <dev/smbus/smbconf.h> 270154897SjmgMODULE_DEPEND(bktr, iicbb, IICBB_MINVER, IICBB_MODVER, IICBB_MAXVER); 271154897SjmgMODULE_DEPEND(bktr, iicbus, IICBUS_MINVER, IICBUS_MODVER, IICBUS_MAXVER); 272154897SjmgMODULE_DEPEND(bktr, smbus, SMBUS_MINVER, SMBUS_MODVER, SMBUS_MAXVER); 273154897Sjmg#endif 27452995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 27565728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27665728SrogerMODULE_VERSION(bktr, 1); 27751694Sroger 27851694Sroger 27951694Sroger/* 28051694Sroger * the boot time probe routine. 28151694Sroger */ 28251694Srogerstatic int 28351694Srogerbktr_probe( device_t dev ) 28451694Sroger{ 28551694Sroger unsigned int type = pci_get_devid(dev); 28651694Sroger unsigned int rev = pci_get_revid(dev); 28751694Sroger 28867306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 28967306Sroger { 29067306Sroger switch (PCI_PRODUCT(type)) { 29167306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 29267306Sroger if (rev == 0x12) 29367306Sroger device_set_desc(dev, "BrookTree 848A"); 29467306Sroger else 29567306Sroger device_set_desc(dev, "BrookTree 848"); 296143163Simp return BUS_PROBE_DEFAULT; 29767306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 29867306Sroger device_set_desc(dev, "BrookTree 849A"); 299143163Simp return BUS_PROBE_DEFAULT; 30067306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 30167306Sroger device_set_desc(dev, "BrookTree 878"); 302143163Simp return BUS_PROBE_DEFAULT; 30367306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 30467306Sroger device_set_desc(dev, "BrookTree 879"); 305143163Simp return BUS_PROBE_DEFAULT; 30667306Sroger } 30751694Sroger }; 30851694Sroger 30951694Sroger return ENXIO; 31051694Sroger} 31151694Sroger 31251694Sroger 31351694Sroger/* 31451694Sroger * the attach routine. 31551694Sroger */ 31651694Srogerstatic int 31751694Srogerbktr_attach( device_t dev ) 31851694Sroger{ 31951694Sroger u_long latency; 32051694Sroger u_long fun; 32151694Sroger unsigned int rev; 32251694Sroger unsigned int unit; 32351694Sroger int error = 0; 32451694Sroger#ifdef BROOKTREE_IRQ 32551694Sroger u_long old_irq, new_irq; 32651694Sroger#endif 32751694Sroger 32851694Sroger struct bktr_softc *bktr = device_get_softc(dev); 32951694Sroger 33051694Sroger unit = device_get_unit(dev); 33151694Sroger 33262112Sroger /* build the device name for bktr_name() */ 33362112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 33462112Sroger 33551694Sroger /* 33651694Sroger * Enable bus mastering and Memory Mapped device 33751694Sroger */ 338254263Sscottl pci_enable_busmaster(dev); 33951694Sroger 34051694Sroger /* 34151694Sroger * Map control/status registers. 34251694Sroger */ 343119690Sjhb bktr->mem_rid = PCIR_BAR(0); 344127135Snjl bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 345127135Snjl &bktr->mem_rid, RF_ACTIVE); 34651694Sroger 34751694Sroger if (!bktr->res_mem) { 34851694Sroger device_printf(dev, "could not map memory\n"); 34951694Sroger error = ENXIO; 35051694Sroger goto fail; 35151694Sroger } 35259014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 35359014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 35451694Sroger 35559014Sroger 35651694Sroger /* 35751694Sroger * Disable the brooktree device 35851694Sroger */ 35959014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 36059014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 36151694Sroger 36251694Sroger 36351694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 36451694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36551694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 36651694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36751694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 36851694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 36951694Sroger#endif 37051694Sroger 37151694Sroger /* 37251694Sroger * Allocate our interrupt. 37351694Sroger */ 37465049Sroger bktr->irq_rid = 0; 375127135Snjl bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 376127135Snjl &bktr->irq_rid, RF_SHAREABLE | RF_ACTIVE); 37751694Sroger if (bktr->res_irq == NULL) { 37851694Sroger device_printf(dev, "could not map interrupt\n"); 37951694Sroger error = ENXIO; 38051694Sroger goto fail; 38151694Sroger } 38251694Sroger 38359250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 384166901Spiso NULL, bktr_intr, bktr, &bktr->res_ih); 38551694Sroger if (error) { 38651694Sroger device_printf(dev, "could not setup irq\n"); 38751694Sroger goto fail; 38851694Sroger 38951694Sroger } 39051694Sroger 39151694Sroger 39251694Sroger /* Update the Device Control Register */ 39351694Sroger /* on Bt878 and Bt879 cards */ 39451694Sroger fun = pci_read_config( dev, 0x40, 2); 39551694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 39651694Sroger 39751694Sroger#if defined( BKTR_430_FX_MODE ) 39851694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 39951694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 40051694Sroger#endif 40151694Sroger 40251694Sroger#if defined( BKTR_SIS_VIA_MODE ) 40351694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 404249585Sgabor fun = fun | 4; /* Enable SiS/VIA compatibility mode (useful for 40551694Sroger OPTi chipset motherboards too */ 40651694Sroger#endif 40751694Sroger pci_write_config(dev, 0x40, fun, 2); 40851694Sroger 40965692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 41093023Snsouch if (bt848_i2c_attach(dev)) 41151694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 41251694Sroger#endif 41351694Sroger 41451694Sroger/* 41551694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 41651694Sroger * you have more than four, then 16 would probably be a better value. 41751694Sroger */ 41851694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 41951694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 42051694Sroger#endif 42151694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 42251694Sroger latency = (latency >> 8) & 0xff; 42351694Sroger if ( bootverbose ) { 42451694Sroger if (latency) 42551694Sroger printf("brooktree%d: PCI bus latency is", unit); 42651694Sroger else 42751694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 42851694Sroger unit); 42951694Sroger } 43051694Sroger if ( !latency ) { 43151694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 43251694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 43351694Sroger } 43451694Sroger if ( bootverbose ) { 43551694Sroger printf(" %d.\n", (int) latency); 43651694Sroger } 43751694Sroger 43851694Sroger /* read the pci device id and revision id */ 43951694Sroger fun = pci_get_devid(dev); 44051694Sroger rev = pci_get_revid(dev); 44151694Sroger 44251694Sroger /* call the common attach code */ 44351694Sroger common_bktr_attach( bktr, unit, fun, rev ); 44451694Sroger 44567306Sroger /* make the device entries */ 44667306Sroger bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 44767306Sroger 0, 0, 0444, "bktr%d", unit); 44867306Sroger bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 44967306Sroger 0, 0, 0444, "tuner%d", unit); 45067306Sroger bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 45167306Sroger 0, 0, 0444, "vbi%d" , unit); 45251694Sroger 45367306Sroger 45467306Sroger /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 45567306Sroger /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 45667306Sroger#if (__FreeBSD_version >=500000) 45767306Sroger if (unit == 0) { 45867306Sroger bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 45967306Sroger bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 46067306Sroger bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 46167306Sroger } 46267306Sroger#endif 46367306Sroger 46451694Sroger return 0; 46551694Sroger 46651694Srogerfail: 46765049Sroger if (bktr->res_irq) 46865049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 46965049Sroger if (bktr->res_mem) 470192805Sed bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 47151694Sroger return error; 47251694Sroger 47351694Sroger} 47451694Sroger 47551694Sroger/* 47651694Sroger * the detach routine. 47751694Sroger */ 47851694Srogerstatic int 47951694Srogerbktr_detach( device_t dev ) 48051694Sroger{ 48151694Sroger struct bktr_softc *bktr = device_get_softc(dev); 48251694Sroger 483118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 484118819Salex /* Disable the soundchip and kernel thread */ 485118819Salex if (bktr->msp3400c_info != NULL) 486118819Salex msp_detach(bktr); 487118819Salex#endif 488118819Salex 48951694Sroger /* Disable the brooktree device */ 49059014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 49159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49251694Sroger 49393023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 49493023Snsouch if (bt848_i2c_detach(dev)) 495115556Sphk printf("bktr%d: i2c_attach: can't attach\n", 496115556Sphk device_get_unit(dev)); 49793023Snsouch#endif 498123088Struckman#ifdef USE_VBIMUTEX 499123088Struckman mtx_destroy(&bktr->vbimutex); 500123088Struckman#endif 50193023Snsouch 50267306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50367306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 50467306Sroger /* then reload the main bktr driver module */ 50551694Sroger 506107699Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices, 507107699Sroger * the aliases for unit 0 are automatically destroyed */ 50867306Sroger destroy_dev(bktr->vbidev); 50967306Sroger destroy_dev(bktr->tunerdev); 51067306Sroger destroy_dev(bktr->bktrdev); 51167306Sroger 51251694Sroger /* 51351694Sroger * Deallocate resources. 51451694Sroger */ 51551694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 51665049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 51765049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 51865049Sroger 51951694Sroger return 0; 52051694Sroger} 52151694Sroger 52251694Sroger/* 52351694Sroger * the shutdown routine. 52451694Sroger */ 52551694Srogerstatic int 52651694Srogerbktr_shutdown( device_t dev ) 52751694Sroger{ 52851694Sroger struct bktr_softc *bktr = device_get_softc(dev); 52951694Sroger 53051694Sroger /* Disable the brooktree device */ 53159014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53259014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 53351694Sroger 53451694Sroger return 0; 53551694Sroger} 53651694Sroger 53751694Sroger 53851694Sroger/* 53951694Sroger * Special Memory Allocation 54051694Sroger */ 54151694Srogervm_offset_t 54251694Srogerget_bktr_mem( int unit, unsigned size ) 54351694Sroger{ 54451694Sroger vm_offset_t addr = 0; 54551694Sroger 546124507Salc addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 547124507Salc 0xffffffff, 1<<24, 0); 54851694Sroger if (addr == 0) 549124507Salc addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 550124507Salc 0xffffffff, PAGE_SIZE, 0); 55151694Sroger if (addr == 0) { 55251694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 55351694Sroger unit, size); 55451694Sroger } 55551694Sroger 55651694Sroger return( addr ); 55751694Sroger} 55851694Sroger 55951694Sroger 56051694Sroger/*--------------------------------------------------------- 56151694Sroger** 56251694Sroger** BrookTree 848 character device driver routines 56351694Sroger** 56451694Sroger**--------------------------------------------------------- 56551694Sroger*/ 56651694Sroger 56751694Sroger#define VIDEO_DEV 0x00 56851694Sroger#define TUNER_DEV 0x01 56951694Sroger#define VBI_DEV 0x02 57051694Sroger 57151694Sroger#define UNIT(x) ((x) & 0x0f) 57251694Sroger#define FUNCTION(x) (x >> 4) 57351694Sroger 57451694Sroger/* 57551694Sroger * 57651694Sroger */ 577104094Sphkstatic int 578130585Sphkbktr_open( struct cdev *dev, int flags, int fmt, struct thread *td ) 57951694Sroger{ 58051694Sroger bktr_ptr_t bktr; 58151694Sroger int unit; 58251694Sroger int result; 58351694Sroger 584183397Sed unit = UNIT( dev2unit(dev) ); 58551694Sroger 58651694Sroger /* Get the device data */ 58751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 58851694Sroger if (bktr == NULL) { 58951694Sroger /* the device is no longer valid/functioning */ 59051694Sroger return (ENXIO); 59151694Sroger } 59251694Sroger 59351694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 59451694Sroger return( ENXIO ); 59551694Sroger 59651694Sroger /* Record that the device is now busy */ 59751694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 59851694Sroger 59951694Sroger 60051694Sroger if (bt848_card != -1) { 60151694Sroger if ((bt848_card >> 8 == unit ) && 60251694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 60351694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 60451694Sroger bktr->bt848_card = (bt848_card & 0xff); 60551694Sroger probeCard(bktr, FALSE, unit); 60651694Sroger } 60751694Sroger } 60851694Sroger } 60951694Sroger 61051694Sroger if (bt848_tuner != -1) { 61151694Sroger if ((bt848_tuner >> 8 == unit ) && 61251694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 61351694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 61451694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 61551694Sroger probeCard(bktr, FALSE, unit); 61651694Sroger } 61751694Sroger } 61851694Sroger } 61951694Sroger 62051694Sroger if (bt848_reverse_mute != -1) { 62159014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 62251694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 62351694Sroger } 62451694Sroger } 62551694Sroger 62659014Sroger if (bt848_slow_msp_audio != -1) { 62759014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 62859014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 62959014Sroger } 63059014Sroger } 63159014Sroger 632118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 633118819Salex if (bt848_stereo_once != 0) { 634118819Salex if ((bt848_stereo_once >> 8) == unit ) { 635118819Salex bktr->stereo_once = (bt848_stereo_once & 0xff); 636118819Salex } 637118819Salex } 638118819Salex 639118819Salex if (bt848_amsound != -1) { 640118819Salex if ((bt848_amsound >> 8) == unit ) { 641118819Salex bktr->amsound = (bt848_amsound & 0xff); 642118819Salex } 643118819Salex } 644118819Salex 645118819Salex if (bt848_dolby != -1) { 646118819Salex if ((bt848_dolby >> 8) == unit ) { 647118819Salex bktr->dolby = (bt848_dolby & 0xff); 648118819Salex } 649118819Salex } 650118819Salex#endif 651118819Salex 652183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 65351694Sroger case VIDEO_DEV: 65451694Sroger result = video_open( bktr ); 65551694Sroger break; 65651694Sroger case TUNER_DEV: 65751694Sroger result = tuner_open( bktr ); 65851694Sroger break; 65951694Sroger case VBI_DEV: 66051694Sroger result = vbi_open( bktr ); 66151694Sroger break; 66251694Sroger default: 66351694Sroger result = ENXIO; 66451694Sroger break; 66551694Sroger } 66651694Sroger 66751694Sroger /* If there was an error opening the device, undo the busy status */ 668196403Sjhb if (result != 0) 66951694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 67051694Sroger return( result ); 67151694Sroger} 67251694Sroger 67351694Sroger 67451694Sroger/* 67551694Sroger * 67651694Sroger */ 677104094Sphkstatic int 678130585Sphkbktr_close( struct cdev *dev, int flags, int fmt, struct thread *td ) 67951694Sroger{ 68051694Sroger bktr_ptr_t bktr; 68151694Sroger int unit; 68251694Sroger int result; 68351694Sroger 684183397Sed unit = UNIT( dev2unit(dev) ); 68551694Sroger 68651694Sroger /* Get the device data */ 68751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 68851694Sroger if (bktr == NULL) { 68951694Sroger /* the device is no longer valid/functioning */ 69051694Sroger return (ENXIO); 69151694Sroger } 69251694Sroger 693183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 69451694Sroger case VIDEO_DEV: 69551694Sroger result = video_close( bktr ); 69651694Sroger break; 69751694Sroger case TUNER_DEV: 69851694Sroger result = tuner_close( bktr ); 69951694Sroger break; 70051694Sroger case VBI_DEV: 70151694Sroger result = vbi_close( bktr ); 70251694Sroger break; 70351694Sroger default: 70451694Sroger return (ENXIO); 705196403Sjhb break; 70651694Sroger } 70751694Sroger 70851694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 70951694Sroger return( result ); 71051694Sroger} 71151694Sroger 71251694Sroger 71351694Sroger/* 71451694Sroger * 71551694Sroger */ 716104094Sphkstatic int 717130585Sphkbktr_read( struct cdev *dev, struct uio *uio, int ioflag ) 71851694Sroger{ 71951694Sroger bktr_ptr_t bktr; 72051694Sroger int unit; 72151694Sroger 722183397Sed unit = UNIT(dev2unit(dev)); 72351694Sroger 72451694Sroger /* Get the device data */ 72551694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 72651694Sroger if (bktr == NULL) { 72751694Sroger /* the device is no longer valid/functioning */ 72851694Sroger return (ENXIO); 72951694Sroger } 73051694Sroger 731183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 73251694Sroger case VIDEO_DEV: 73351694Sroger return( video_read( bktr, unit, dev, uio ) ); 73451694Sroger case VBI_DEV: 73551694Sroger return( vbi_read( bktr, uio, ioflag ) ); 73651694Sroger } 73751694Sroger return( ENXIO ); 73851694Sroger} 73951694Sroger 74051694Sroger 74151694Sroger/* 74251694Sroger * 74351694Sroger */ 744104094Sphkstatic int 745130585Sphkbktr_write( struct cdev *dev, struct uio *uio, int ioflag ) 74651694Sroger{ 74751694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 74851694Sroger} 74951694Sroger 75051694Sroger 75151694Sroger/* 75251694Sroger * 75351694Sroger */ 754104094Sphkstatic int 755130585Sphkbktr_ioctl( struct cdev *dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 75651694Sroger{ 75751694Sroger bktr_ptr_t bktr; 75851694Sroger int unit; 75951694Sroger 760183397Sed unit = UNIT(dev2unit(dev)); 76151694Sroger 76251694Sroger /* Get the device data */ 76351694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76451694Sroger if (bktr == NULL) { 76551694Sroger /* the device is no longer valid/functioning */ 76651694Sroger return (ENXIO); 76751694Sroger } 76851694Sroger 769158937Sjmg#ifdef BKTR_GPIO_ACCESS 770158937Sjmg if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN && 771158937Sjmg cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA && 772158937Sjmg cmd != BT848_GPIO_SET_DATA) /* no frame buffer allocated (ioctl failed) */ 773158937Sjmg return( ENOMEM ); 774158937Sjmg#else 77551694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 77651694Sroger return( ENOMEM ); 777158937Sjmg#endif 77851694Sroger 779183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 78051694Sroger case VIDEO_DEV: 78183366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 78251694Sroger case TUNER_DEV: 78383366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 78451694Sroger } 78551694Sroger 78651694Sroger return( ENXIO ); 78751694Sroger} 78851694Sroger 78951694Sroger 79051694Sroger/* 79151694Sroger * 79251694Sroger */ 793104094Sphkstatic int 794201223Srnolandbktr_mmap( struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 795201223Srnoland int nprot, vm_memattr_t *memattr ) 79651694Sroger{ 79751694Sroger int unit; 79851694Sroger bktr_ptr_t bktr; 79951694Sroger 800183397Sed unit = UNIT(dev2unit(dev)); 80151694Sroger 802183397Sed if (FUNCTION(dev2unit(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 80351694Sroger return( -1 ); 80451694Sroger 80551694Sroger /* Get the device data */ 80651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 80751694Sroger if (bktr == NULL) { 80851694Sroger /* the device is no longer valid/functioning */ 80951694Sroger return (ENXIO); 81051694Sroger } 81151694Sroger 81251694Sroger if (nprot & PROT_EXEC) 81351694Sroger return( -1 ); 81451694Sroger 81551694Sroger if (offset < 0) 81651694Sroger return( -1 ); 81751694Sroger 81851694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 81951694Sroger return( -1 ); 82051694Sroger 821111462Smux *paddr = vtophys(bktr->bigbuf) + offset; 822111462Smux return( 0 ); 82351694Sroger} 82451694Sroger 825104094Sphkstatic int 826130585Sphkbktr_poll( struct cdev *dev, int events, struct thread *td) 82751694Sroger{ 82851694Sroger int unit; 82951694Sroger bktr_ptr_t bktr; 83051694Sroger int revents = 0; 83159277Sroger DECLARE_INTR_MASK(s); 83251694Sroger 833183397Sed unit = UNIT(dev2unit(dev)); 83451694Sroger 83551694Sroger /* Get the device data */ 83651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 83751694Sroger if (bktr == NULL) { 83851694Sroger /* the device is no longer valid/functioning */ 83951694Sroger return (ENXIO); 84051694Sroger } 84151694Sroger 842123088Struckman LOCK_VBI(bktr); 84359277Sroger DISABLE_INTR(s); 84451694Sroger 84551694Sroger if (events & (POLLIN | POLLRDNORM)) { 84651694Sroger 847183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 84851694Sroger case VBI_DEV: 84951694Sroger if(bktr->vbisize == 0) 85083366Sjulian selrecord(td, &bktr->vbi_select); 85151694Sroger else 85251694Sroger revents |= events & (POLLIN | POLLRDNORM); 85351694Sroger break; 85451694Sroger } 85551694Sroger } 85651694Sroger 85759250Sroger ENABLE_INTR(s); 858123088Struckman UNLOCK_VBI(bktr); 85951694Sroger 86051694Sroger return (revents); 86151694Sroger} 86251694Sroger 86351694Sroger/*****************/ 86451694Sroger/* *** BSDI *** */ 86551694Sroger/*****************/ 86651694Sroger 86751694Sroger#if defined(__bsdi__) 86851694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 86951694Sroger 87051694Sroger 87151694Sroger/*****************************/ 87251694Sroger/* *** OpenBSD / NetBSD *** */ 87351694Sroger/*****************************/ 87451694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 87559014Sroger 87659014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 87759014Sroger 87859014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 87959014Sroger 88059014Sroger#define bktr_open bktropen 88159014Sroger#define bktr_close bktrclose 88259014Sroger#define bktr_read bktrread 88359014Sroger#define bktr_write bktrwrite 88459014Sroger#define bktr_ioctl bktrioctl 88559014Sroger#define bktr_mmap bktrmmap 88659014Sroger 88759014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 88859014Sroger vm_offset_t, vm_offset_t); 88959014Sroger 89062112Sroger#if defined(__OpenBSD__) 89192739Salfredstatic int bktr_probe(struct device *, void *, void *); 89259014Sroger#else 89392739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 89459014Sroger#endif 89592739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 89659014Sroger 89759014Srogerstruct cfattach bktr_ca = { 89859014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 89959014Sroger}; 90059014Sroger 90159014Sroger#if defined(__NetBSD__) 90259014Srogerextern struct cfdriver bktr_cd; 90359014Sroger#else 90459014Srogerstruct cfdriver bktr_cd = { 90559014Sroger NULL, "bktr", DV_DULL 90659014Sroger}; 90759014Sroger#endif 90859014Sroger 90962112Srogerint 91062112Srogerbktr_probe(parent, match, aux) 91162112Sroger struct device *parent; 91262112Sroger#if defined(__OpenBSD__) 91359014Sroger void *match; 91459014Sroger#else 91559014Sroger struct cfdata *match; 91659014Sroger#endif 91759014Sroger void *aux; 91859014Sroger{ 91959014Sroger struct pci_attach_args *pa = aux; 92059014Sroger 92159014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 92259014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 92359014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 92459014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 92559014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 92659014Sroger return 1; 92759014Sroger 92859014Sroger return 0; 92959014Sroger} 93059014Sroger 93159014Sroger 93259014Sroger/* 93359014Sroger * the attach routine. 93459014Sroger */ 93559014Srogerstatic void 93662112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 93759014Sroger{ 93859014Sroger bktr_ptr_t bktr; 93959014Sroger u_long latency; 94059014Sroger u_long fun; 94159014Sroger unsigned int rev; 94259014Sroger 94359014Sroger#if defined(__OpenBSD__) 94459014Sroger struct pci_attach_args *pa = aux; 94559014Sroger pci_chipset_tag_t pc = pa->pa_pc; 94659014Sroger 94759014Sroger pci_intr_handle_t ih; 94859014Sroger const char *intrstr; 94959014Sroger int retval; 95059014Sroger int unit; 95159014Sroger 95259014Sroger bktr = (bktr_ptr_t)self; 95359014Sroger unit = bktr->bktr_dev.dv_unit; 95459014Sroger 95559014Sroger bktr->pc = pa->pa_pc; 95659014Sroger bktr->tag = pa->pa_tag; 95759014Sroger bktr->dmat = pa->pa_dmat; 95859014Sroger 95959014Sroger /* 96059014Sroger * map memory 96159014Sroger */ 96259014Sroger bktr->memt = pa->pa_memt; 96359014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 96459014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 96559014Sroger if (!retval) 96659014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 96759014Sroger bktr->obmemsz, 0, &bktr->memh); 96859014Sroger if (retval) { 96959014Sroger printf(": couldn't map memory\n"); 97059014Sroger return; 97159014Sroger } 97259014Sroger 97359014Sroger 97459014Sroger /* 97559014Sroger * map interrupt 97659014Sroger */ 97759014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 97859014Sroger pa->pa_intrline, &ih)) { 97959014Sroger printf(": couldn't map interrupt\n"); 98059014Sroger return; 98159014Sroger } 98259014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 98359014Sroger 98459014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 98559014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 98659014Sroger if (bktr->ih == NULL) { 98759014Sroger printf(": couldn't establish interrupt"); 98859014Sroger if (intrstr != NULL) 98959014Sroger printf(" at %s", intrstr); 99059014Sroger printf("\n"); 99159014Sroger return; 99259014Sroger } 99359014Sroger 99459014Sroger if (intrstr != NULL) 99559014Sroger printf(": %s\n", intrstr); 99659014Sroger#endif /* __OpenBSD__ */ 99759014Sroger 99859014Sroger#if defined(__NetBSD__) 99959014Sroger struct pci_attach_args *pa = aux; 100059014Sroger pci_intr_handle_t ih; 100159014Sroger const char *intrstr; 100259014Sroger int retval; 100359014Sroger int unit; 100459014Sroger 100559014Sroger bktr = (bktr_ptr_t)self; 100659014Sroger unit = bktr->bktr_dev.dv_unit; 100759014Sroger bktr->dmat = pa->pa_dmat; 100859014Sroger 100959014Sroger printf("\n"); 101059014Sroger 101159014Sroger /* 101259014Sroger * map memory 101359014Sroger */ 101459014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 101562112Sroger PCI_MAPREG_TYPE_MEM 101662112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 101762112Sroger &bktr->memt, &bktr->memh, NULL, 101862112Sroger &bktr->obmemsz); 101962112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 102062112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 102159014Sroger if (retval) { 102262112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 102359014Sroger return; 102459014Sroger } 102559014Sroger 102659014Sroger /* 102759014Sroger * Disable the brooktree device 102859014Sroger */ 102959014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 103059014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 103159014Sroger 103259014Sroger /* 103359014Sroger * map interrupt 103459014Sroger */ 103559014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 103659014Sroger pa->pa_intrline, &ih)) { 103762112Sroger printf("%s: couldn't map interrupt\n", 103862112Sroger bktr_name(bktr)); 103959014Sroger return; 104059014Sroger } 104159014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 104259014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 104359014Sroger bktr_intr, bktr); 104459014Sroger if (bktr->ih == NULL) { 104559014Sroger printf("%s: couldn't establish interrupt", 104662112Sroger bktr_name(bktr)); 104762112Sroger if (intrstr != NULL) 104862112Sroger printf(" at %s", intrstr); 104962112Sroger printf("\n"); 105062112Sroger return; 105159014Sroger } 105259014Sroger if (intrstr != NULL) 105362112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 105459014Sroger intrstr); 105559014Sroger#endif /* __NetBSD__ */ 105659014Sroger 105759014Sroger/* 105859014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 105959014Sroger * you have more than four, then 16 would probably be a better value. 106059014Sroger */ 106159014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 106259014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 106359014Sroger#endif 106459014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 106559014Sroger latency = (latency >> 8) & 0xff; 106659014Sroger 106762112Sroger if (!latency) { 106862112Sroger if (bootverbose) { 106959014Sroger printf("%s: PCI bus latency was 0 changing to %d", 107062112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 107159014Sroger } 107259014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 107359014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 107459014Sroger PCI_LATENCY_TIMER, latency<<8); 107559014Sroger } 107659014Sroger 107759014Sroger 107862112Sroger /* Enabled Bus Master 107962112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 108062112Sroger boot) */ 108159014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 108262112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 108362112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 108459014Sroger 108559014Sroger /* read the pci id and determine the card type */ 108659014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 108759014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 108859014Sroger 108962112Sroger common_bktr_attach(bktr, unit, fun, rev); 109059014Sroger} 109159014Sroger 109259014Sroger 109359014Sroger/* 109459014Sroger * Special Memory Allocation 109559014Sroger */ 109659014Srogervm_offset_t 109759014Srogerget_bktr_mem(bktr, dmapp, size) 109859014Sroger bktr_ptr_t bktr; 109959014Sroger bus_dmamap_t *dmapp; 110059014Sroger unsigned int size; 110159014Sroger{ 110259014Sroger bus_dma_tag_t dmat = bktr->dmat; 110359014Sroger bus_dma_segment_t seg; 110459014Sroger bus_size_t align; 110559014Sroger int rseg; 110659014Sroger caddr_t kva; 110759014Sroger 110859014Sroger /* 110959014Sroger * Allocate a DMA area 111059014Sroger */ 111159014Sroger align = 1 << 24; 111259014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111359014Sroger &rseg, BUS_DMA_NOWAIT)) { 111459014Sroger align = PAGE_SIZE; 111559014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111659014Sroger &rseg, BUS_DMA_NOWAIT)) { 111762112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 111862112Sroger bktr_name(bktr), size); 111959014Sroger return 0; 112059014Sroger } 112159014Sroger } 112259014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 112359014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 112462112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 112562112Sroger bktr_name(bktr), size); 112659014Sroger bus_dmamem_free(dmat, &seg, rseg); 112759014Sroger return 0; 112859014Sroger } 112959014Sroger#ifdef __OpenBSD__ 113059014Sroger bktr->dm_mapsize = size; 113159014Sroger#endif 113259014Sroger /* 113359014Sroger * Create and locd the DMA map for the DMA area 113459014Sroger */ 113559014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 113662112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 113762112Sroger bktr_name(bktr), size); 113859014Sroger bus_dmamem_unmap(dmat, kva, size); 113959014Sroger bus_dmamem_free(dmat, &seg, rseg); 114059014Sroger return 0; 114159014Sroger } 114259014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 114362112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 114462112Sroger bktr_name(bktr), size); 114559014Sroger bus_dmamem_unmap(dmat, kva, size); 114659014Sroger bus_dmamem_free(dmat, &seg, rseg); 114759014Sroger bus_dmamap_destroy(dmat, *dmapp); 114859014Sroger return 0; 114959014Sroger } 115059014Sroger return (vm_offset_t)kva; 115159014Sroger} 115259014Sroger 115359014Srogervoid 115459014Srogerfree_bktr_mem(bktr, dmap, kva) 115559014Sroger bktr_ptr_t bktr; 115659014Sroger bus_dmamap_t dmap; 115759014Sroger vm_offset_t kva; 115859014Sroger{ 115959014Sroger bus_dma_tag_t dmat = bktr->dmat; 116059014Sroger 116159014Sroger#ifdef __NetBSD__ 116259014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 116359014Sroger#else 116459014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 116559014Sroger#endif 116659014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 116759014Sroger bus_dmamap_destroy(dmat, dmap); 116859014Sroger} 116959014Sroger 117059014Sroger 117159014Sroger/*--------------------------------------------------------- 117259014Sroger** 117359014Sroger** BrookTree 848 character device driver routines 117459014Sroger** 117559014Sroger**--------------------------------------------------------- 117659014Sroger*/ 117759014Sroger 117859014Sroger 117959014Sroger#define VIDEO_DEV 0x00 118059014Sroger#define TUNER_DEV 0x01 118159014Sroger#define VBI_DEV 0x02 118259014Sroger 1183183397Sed#define UNIT(x) (dev2unit((x) & 0x0f)) 1184183397Sed#define FUNCTION(x) (dev2unit((x >> 4) & 0x0f)) 118559014Sroger 118659014Sroger/* 118759014Sroger * 118859014Sroger */ 118959014Srogerint 119083366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 119159014Sroger{ 119259014Sroger bktr_ptr_t bktr; 119359014Sroger int unit; 119459014Sroger 119562112Sroger unit = UNIT(dev); 119659014Sroger 119759014Sroger /* unit out of range */ 119859014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 119962112Sroger return(ENXIO); 120059014Sroger 120159014Sroger bktr = bktr_cd.cd_devs[unit]; 120259014Sroger 120359014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 120462112Sroger return(ENXIO); 120559014Sroger 120662112Sroger switch (FUNCTION(dev)) { 120759014Sroger case VIDEO_DEV: 120862112Sroger return(video_open(bktr)); 120959014Sroger case TUNER_DEV: 121062112Sroger return(tuner_open(bktr)); 121159014Sroger case VBI_DEV: 121262112Sroger return(vbi_open(bktr)); 121359014Sroger } 121459014Sroger 121562112Sroger return(ENXIO); 121659014Sroger} 121759014Sroger 121859014Sroger 121959014Sroger/* 122059014Sroger * 122159014Sroger */ 122259014Srogerint 122383366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 122459014Sroger{ 122559014Sroger bktr_ptr_t bktr; 122659014Sroger int unit; 122759014Sroger 122862112Sroger unit = UNIT(dev); 122959014Sroger 123059014Sroger bktr = bktr_cd.cd_devs[unit]; 123159014Sroger 123262112Sroger switch (FUNCTION(dev)) { 123359014Sroger case VIDEO_DEV: 123462112Sroger return(video_close(bktr)); 123559014Sroger case TUNER_DEV: 123662112Sroger return(tuner_close(bktr)); 123759014Sroger case VBI_DEV: 123862112Sroger return(vbi_close(bktr)); 123959014Sroger } 124059014Sroger 124162112Sroger return(ENXIO); 124259014Sroger} 124359014Sroger 124459014Sroger/* 124559014Sroger * 124659014Sroger */ 124759014Srogerint 124862112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 124959014Sroger{ 125059014Sroger bktr_ptr_t bktr; 125159014Sroger int unit; 125259014Sroger 125362112Sroger unit = UNIT(dev); 125459014Sroger 125559014Sroger bktr = bktr_cd.cd_devs[unit]; 125659014Sroger 125762112Sroger switch (FUNCTION(dev)) { 125859014Sroger case VIDEO_DEV: 125962112Sroger return(video_read(bktr, unit, dev, uio)); 126059014Sroger case VBI_DEV: 126162112Sroger return(vbi_read(bktr, uio, ioflag)); 126259014Sroger } 126359014Sroger 126462112Sroger return(ENXIO); 126559014Sroger} 126659014Sroger 126759014Sroger 126859014Sroger/* 126959014Sroger * 127059014Sroger */ 127159014Srogerint 127262112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 127359014Sroger{ 127459014Sroger /* operation not supported */ 127562112Sroger return(EOPNOTSUPP); 127659014Sroger} 127759014Sroger 127859014Sroger/* 127959014Sroger * 128059014Sroger */ 128159014Srogerint 128283366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 128359014Sroger{ 128459014Sroger bktr_ptr_t bktr; 128559014Sroger int unit; 128659014Sroger 128762112Sroger unit = UNIT(dev); 128859014Sroger 128959014Sroger bktr = bktr_cd.cd_devs[unit]; 129059014Sroger 129159014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 129262112Sroger return(ENOMEM); 129359014Sroger 129462112Sroger switch (FUNCTION(dev)) { 129559014Sroger case VIDEO_DEV: 129662112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 129759014Sroger case TUNER_DEV: 129862112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 129959014Sroger } 130059014Sroger 130162112Sroger return(ENXIO); 130259014Sroger} 130359014Sroger 130459014Sroger/* 130559014Sroger * 130659014Sroger */ 130762214Srogerpaddr_t 130862214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 130959014Sroger{ 131059014Sroger int unit; 131159014Sroger bktr_ptr_t bktr; 131259014Sroger 131362112Sroger unit = UNIT(dev); 131459014Sroger 131562112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 131662112Sroger return(-1); 131759014Sroger 131859014Sroger bktr = bktr_cd.cd_devs[unit]; 131959014Sroger 132062112Sroger if ((vaddr_t)offset < 0) 132162112Sroger return(-1); 132259014Sroger 132362112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 132462112Sroger return(-1); 132559014Sroger 132659014Sroger#ifdef __NetBSD__ 132759014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 132862112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 132959014Sroger#else 133062112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 133159014Sroger#endif 133259014Sroger} 133359014Sroger 133451694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1335