bktr_os.c revision 256281
11573Srgrimes/*- 21573Srgrimes * 1. Redistributions of source code must retain the 31573Srgrimes * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 41573Srgrimes * All rights reserved. 51573Srgrimes * 61573Srgrimes * Redistribution and use in source and binary forms, with or without 71573Srgrimes * modification, are permitted provided that the following conditions 81573Srgrimes * are met: 91573Srgrimes * 1. Redistributions of source code must retain the above copyright 101573Srgrimes * notice, this list of conditions and the following disclaimer. 111573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer in the 131573Srgrimes * documentation and/or other materials provided with the distribution. 141573Srgrimes * 3. All advertising materials mentioning features or use of this software 151573Srgrimes * must display the following acknowledgement: 161573Srgrimes * This product includes software developed by Amancio Hasty and 171573Srgrimes * Roger Hardiman 181573Srgrimes * 4. The name of the author may not be used to endorse or promote products 191573Srgrimes * derived from this software without specific prior written permission. 201573Srgrimes * 211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 221573Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 231573Srgrimes * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 241573Srgrimes * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 251573Srgrimes * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 261573Srgrimes * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 271573Srgrimes * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 291573Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 301573Srgrimes * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 311573Srgrimes * POSSIBILITY OF SUCH DAMAGE. 321573Srgrimes */ 331573Srgrimes 341573Srgrimes#include <sys/cdefs.h> 351573Srgrimes__FBSDID("$FreeBSD: stable/10/sys/dev/bktr/bktr_os.c 254263 2013-08-12 23:30:01Z scottl $"); 361573Srgrimes 371573Srgrimes/* 381573Srgrimes * This is part of the Driver for Video Capture Cards (Frame grabbers) 391573Srgrimes * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 401573Srgrimes * chipset. 411573Srgrimes * Copyright Roger Hardiman and Amancio Hasty. 421573Srgrimes * 431573Srgrimes * bktr_os : This has all the Operating System dependant code, 441573Srgrimes * probe/attach and open/close/ioctl/read/mmap 451573Srgrimes * memory allocation 461573Srgrimes * PCI bus interfacing 471573Srgrimes */ 481573Srgrimes 491573Srgrimes#include "opt_bktr.h" /* include any kernel config options */ 501573Srgrimes 511573Srgrimes#define FIFO_RISC_DISABLED 0 521573Srgrimes#define ALL_INTS_DISABLED 0 531573Srgrimes 541573Srgrimes 551573Srgrimes/*******************/ 561573Srgrimes/* *** FreeBSD *** */ 571573Srgrimes/*******************/ 581573Srgrimes#ifdef __FreeBSD__ 591573Srgrimes 601573Srgrimes#include <sys/param.h> 611573Srgrimes#include <sys/systm.h> 621573Srgrimes#include <sys/conf.h> 631573Srgrimes#include <sys/uio.h> 641573Srgrimes#include <sys/kernel.h> 651573Srgrimes#include <sys/module.h> 661573Srgrimes#include <sys/signalvar.h> 671573Srgrimes#include <sys/malloc.h> 681573Srgrimes#include <sys/mman.h> 691573Srgrimes#include <sys/poll.h> 701573Srgrimes#if __FreeBSD_version >= 500014 711573Srgrimes#include <sys/selinfo.h> 721573Srgrimes#else 731573Srgrimes#include <sys/select.h> 741573Srgrimes#endif 751573Srgrimes 761573Srgrimes#include <vm/vm.h> 771573Srgrimes#include <vm/vm_kern.h> 781573Srgrimes#include <vm/pmap.h> 791573Srgrimes#include <vm/vm_extern.h> 801573Srgrimes 811573Srgrimes#include <sys/bus.h> /* used by smbus and newbus */ 821573Srgrimes 831573Srgrimes#include <machine/bus.h> /* used by bus space and newbus */ 841573Srgrimes#include <sys/bus.h> 851573Srgrimes 861573Srgrimes#include <sys/rman.h> /* used by newbus */ 871573Srgrimes#include <machine/resource.h> /* used by newbus */ 881573Srgrimes 891573Srgrimes#if (__FreeBSD_version < 500000) 901573Srgrimes#include <machine/clock.h> /* for DELAY */ 911573Srgrimes#include <pci/pcivar.h> 921573Srgrimes#include <pci/pcireg.h> 931573Srgrimes#else 941573Srgrimes#include <dev/pci/pcivar.h> 951573Srgrimes#include <dev/pci/pcireg.h> 961573Srgrimes#endif 971573Srgrimes 981573Srgrimes#include <sys/sysctl.h> 991573Srgrimesint bt848_card = -1; 1001573Srgrimesint bt848_tuner = -1; 1011573Srgrimesint bt848_reverse_mute = -1; 1021573Srgrimesint bt848_format = -1; 1031573Srgrimesint bt848_slow_msp_audio = -1; 1041573Srgrimes#ifdef BKTR_NEW_MSP34XX_DRIVER 1051573Srgrimesint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 1061573Srgrimesint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 1071573Srgrimes the autoscan seems work well only with FM... */ 1081573Srgrimesint bt848_dolby = 0; 1091573Srgrimes#endif 1101573Srgrimes 1111573Srgrimesstatic SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 1121573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 1131573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 1141573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 1151573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 1161573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 1171573Srgrimes#ifdef BKTR_NEW_MSP34XX_DRIVER 1181573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 1191573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 1201573SrgrimesSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 1211573Srgrimes#endif 1221573Srgrimes 1231573Srgrimes#endif /* end freebsd section */ 1241573Srgrimes 1251573Srgrimes 1261573Srgrimes 1271573Srgrimes/****************/ 1281573Srgrimes/* *** BSDI *** */ 1291573Srgrimes/****************/ 1301573Srgrimes#ifdef __bsdi__ 1311573Srgrimes#endif /* __bsdi__ */ 1321573Srgrimes 1331573Srgrimes 1341573Srgrimes/**************************/ 1351573Srgrimes/* *** OpenBSD/NetBSD *** */ 1361573Srgrimes/**************************/ 1371573Srgrimes#if defined(__NetBSD__) || defined(__OpenBSD__) 1381573Srgrimes 1391573Srgrimes#include <sys/param.h> 1401573Srgrimes#include <sys/systm.h> 1411573Srgrimes#include <sys/conf.h> 1421573Srgrimes#include <sys/uio.h> 1431573Srgrimes#include <sys/kernel.h> 1441573Srgrimes#include <sys/signalvar.h> 1451573Srgrimes#include <sys/mman.h> 1461573Srgrimes#include <sys/poll.h> 1471573Srgrimes#include <sys/select.h> 1481573Srgrimes#include <sys/vnode.h> 1491573Srgrimes 1501573Srgrimes#include <vm/vm.h> 1511573Srgrimes 1521573Srgrimes#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 1531573Srgrimes 1541573Srgrimes#ifndef __NetBSD__ 1551573Srgrimes#include <vm/vm_kern.h> 1561573Srgrimes#include <vm/pmap.h> 1571573Srgrimes#include <vm/vm_extern.h> 1581573Srgrimes#endif 1591573Srgrimes 1601573Srgrimes#include <sys/device.h> 1611573Srgrimes#include <dev/pci/pcivar.h> 1621573Srgrimes#include <dev/pci/pcireg.h> 1631573Srgrimes#include <dev/pci/pcidevs.h> 1641573Srgrimes 1651573Srgrimes#define BKTR_DEBUG 1661573Srgrimes#ifdef BKTR_DEBUG 1671573Srgrimesint bktr_debug = 0; 1681573Srgrimes#define DPR(x) (bktr_debug ? printf x : 0) 1691573Srgrimes#else 1701573Srgrimes#define DPR(x) 1711573Srgrimes#endif 1721573Srgrimes#endif /* __NetBSD__ || __OpenBSD__ */ 1731573Srgrimes 1741573Srgrimes 1751573Srgrimes#ifdef __NetBSD__ 1761573Srgrimes#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 1771573Srgrimes#include <dev/pci/bktr/bktr_reg.h> 1781573Srgrimes#include <dev/pci/bktr/bktr_tuner.h> 1791573Srgrimes#include <dev/pci/bktr/bktr_card.h> 1801573Srgrimes#include <dev/pci/bktr/bktr_audio.h> 1811573Srgrimes#include <dev/pci/bktr/bktr_core.h> 1821573Srgrimes#include <dev/pci/bktr/bktr_os.h> 1831573Srgrimes#else /* Traditional location for .h files */ 1841573Srgrimes#include <dev/bktr/ioctl_meteor.h> 1851573Srgrimes#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 1861573Srgrimes#include <dev/bktr/bktr_reg.h> 1871573Srgrimes#include <dev/bktr/bktr_tuner.h> 1881573Srgrimes#include <dev/bktr/bktr_card.h> 1891573Srgrimes#include <dev/bktr/bktr_audio.h> 1901573Srgrimes#include <dev/bktr/bktr_core.h> 1911573Srgrimes#include <dev/bktr/bktr_os.h> 1921573Srgrimes 1931573Srgrimes#if defined(BKTR_USE_FREEBSD_SMBUS) 1941573Srgrimes#include <dev/bktr/bktr_i2c.h> 1951573Srgrimes 1961573Srgrimes#include "iicbb_if.h" 1971573Srgrimes#include "smbus_if.h" 1981573Srgrimes#endif 1991573Srgrimes#endif 2001573Srgrimes 2011573Srgrimes 2021573Srgrimes/****************************/ 2031573Srgrimes/* *** FreeBSD 4.x code *** */ 2041573Srgrimes/****************************/ 2051573Srgrimes 2061573Srgrimesstatic int bktr_probe( device_t dev ); 2071573Srgrimesstatic int bktr_attach( device_t dev ); 2081573Srgrimesstatic int bktr_detach( device_t dev ); 2091573Srgrimesstatic int bktr_shutdown( device_t dev ); 2101573Srgrimesstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 2111573Srgrimes 2121573Srgrimesstatic device_method_t bktr_methods[] = { 2131573Srgrimes /* Device interface */ 2141573Srgrimes DEVMETHOD(device_probe, bktr_probe), 2151573Srgrimes DEVMETHOD(device_attach, bktr_attach), 2161573Srgrimes DEVMETHOD(device_detach, bktr_detach), 2171573Srgrimes DEVMETHOD(device_shutdown, bktr_shutdown), 2181573Srgrimes 2191573Srgrimes#if defined(BKTR_USE_FREEBSD_SMBUS) 2201573Srgrimes /* iicbb interface */ 2211573Srgrimes DEVMETHOD(iicbb_callback, bti2c_iic_callback), 2221573Srgrimes DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 2231573Srgrimes DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 2241573Srgrimes DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 2251573Srgrimes DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 2261573Srgrimes DEVMETHOD(iicbb_reset, bti2c_iic_reset), 2271573Srgrimes 2281573Srgrimes /* smbus interface */ 2291573Srgrimes DEVMETHOD(smbus_callback, bti2c_smb_callback), 2301573Srgrimes DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 2311573Srgrimes DEVMETHOD(smbus_writew, bti2c_smb_writew), 2321573Srgrimes DEVMETHOD(smbus_readb, bti2c_smb_readb), 2331573Srgrimes#endif 2341573Srgrimes 2351573Srgrimes { 0, 0 } 2361573Srgrimes}; 2371573Srgrimes 2381573Srgrimesstatic driver_t bktr_driver = { 2391573Srgrimes "bktr", 2401573Srgrimes bktr_methods, 2411573Srgrimes sizeof(struct bktr_softc), 2421573Srgrimes}; 2431573Srgrimes 2441573Srgrimesstatic devclass_t bktr_devclass; 2451573Srgrimes 2461573Srgrimesstatic d_open_t bktr_open; 2471573Srgrimesstatic d_close_t bktr_close; 2481573Srgrimesstatic d_read_t bktr_read; 2491573Srgrimesstatic d_write_t bktr_write; 2501573Srgrimesstatic d_ioctl_t bktr_ioctl; 2511573Srgrimesstatic d_mmap_t bktr_mmap; 2521573Srgrimesstatic d_poll_t bktr_poll; 2531573Srgrimes 2541573Srgrimesstatic struct cdevsw bktr_cdevsw = { 2551573Srgrimes .d_version = D_VERSION, 2561573Srgrimes .d_flags = D_NEEDGIANT, 2571573Srgrimes .d_open = bktr_open, 2581573Srgrimes .d_close = bktr_close, 2591573Srgrimes .d_read = bktr_read, 2601573Srgrimes .d_write = bktr_write, 2611573Srgrimes .d_ioctl = bktr_ioctl, 2621573Srgrimes .d_poll = bktr_poll, 2631573Srgrimes .d_mmap = bktr_mmap, 2641573Srgrimes .d_name = "bktr", 2651573Srgrimes}; 2661573Srgrimes 2671573Srgrimes#ifdef BKTR_USE_FREEBSD_SMBUS 2681573Srgrimes#include <dev/iicbus/iiconf.h> 2691573Srgrimes#include <dev/smbus/smbconf.h> 2701573SrgrimesMODULE_DEPEND(bktr, iicbb, IICBB_MINVER, IICBB_MODVER, IICBB_MAXVER); 2711573SrgrimesMODULE_DEPEND(bktr, iicbus, IICBUS_MINVER, IICBUS_MODVER, IICBUS_MAXVER); 2721573SrgrimesMODULE_DEPEND(bktr, smbus, SMBUS_MINVER, SMBUS_MODVER, SMBUS_MAXVER); 2731573Srgrimes#endif 2741573SrgrimesDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 2751573SrgrimesMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 2761573SrgrimesMODULE_VERSION(bktr, 1); 2771573Srgrimes 2781573Srgrimes 2791573Srgrimes/* 2801573Srgrimes * the boot time probe routine. 2811573Srgrimes */ 2821573Srgrimesstatic int 2831573Srgrimesbktr_probe( device_t dev ) 2841573Srgrimes{ 2851573Srgrimes unsigned int type = pci_get_devid(dev); 2861573Srgrimes unsigned int rev = pci_get_revid(dev); 2871573Srgrimes 2881573Srgrimes if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 2891573Srgrimes { 2901573Srgrimes switch (PCI_PRODUCT(type)) { 2911573Srgrimes case PCI_PRODUCT_BROOKTREE_BT848: 2921573Srgrimes if (rev == 0x12) 2931573Srgrimes device_set_desc(dev, "BrookTree 848A"); 2941573Srgrimes else 2951573Srgrimes device_set_desc(dev, "BrookTree 848"); 2961573Srgrimes return BUS_PROBE_DEFAULT; 2971573Srgrimes case PCI_PRODUCT_BROOKTREE_BT849: 2981573Srgrimes device_set_desc(dev, "BrookTree 849A"); 2991573Srgrimes return BUS_PROBE_DEFAULT; 3001573Srgrimes case PCI_PRODUCT_BROOKTREE_BT878: 3011573Srgrimes device_set_desc(dev, "BrookTree 878"); 3021573Srgrimes return BUS_PROBE_DEFAULT; 3031573Srgrimes case PCI_PRODUCT_BROOKTREE_BT879: 3041573Srgrimes device_set_desc(dev, "BrookTree 879"); 3051573Srgrimes return BUS_PROBE_DEFAULT; 3061573Srgrimes } 3071573Srgrimes }; 3081573Srgrimes 3091573Srgrimes return ENXIO; 3101573Srgrimes} 3111573Srgrimes 3121573Srgrimes 3131573Srgrimes/* 3141573Srgrimes * the attach routine. 3151573Srgrimes */ 3161573Srgrimesstatic int 3171573Srgrimesbktr_attach( device_t dev ) 3181573Srgrimes{ 3191573Srgrimes u_long latency; 3201573Srgrimes u_long fun; 3211573Srgrimes unsigned int rev; 3221573Srgrimes unsigned int unit; 3231573Srgrimes int error = 0; 3241573Srgrimes#ifdef BROOKTREE_IRQ 3251573Srgrimes u_long old_irq, new_irq; 3261573Srgrimes#endif 3271573Srgrimes 3281573Srgrimes struct bktr_softc *bktr = device_get_softc(dev); 3291573Srgrimes 3301573Srgrimes unit = device_get_unit(dev); 3311573Srgrimes 3321573Srgrimes /* build the device name for bktr_name() */ 3331573Srgrimes snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 3341573Srgrimes 3351573Srgrimes /* 3361573Srgrimes * Enable bus mastering and Memory Mapped device 3371573Srgrimes */ 3381573Srgrimes pci_enable_busmaster(dev); 3391573Srgrimes 3401573Srgrimes /* 3411573Srgrimes * Map control/status registers. 3421573Srgrimes */ 3431573Srgrimes bktr->mem_rid = PCIR_BAR(0); 3441573Srgrimes bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 3451573Srgrimes &bktr->mem_rid, RF_ACTIVE); 3461573Srgrimes 3471573Srgrimes if (!bktr->res_mem) { 3481573Srgrimes device_printf(dev, "could not map memory\n"); 3491573Srgrimes error = ENXIO; 3501573Srgrimes goto fail; 3511573Srgrimes } 3521573Srgrimes bktr->memt = rman_get_bustag(bktr->res_mem); 3531573Srgrimes bktr->memh = rman_get_bushandle(bktr->res_mem); 3541573Srgrimes 3551573Srgrimes 3561573Srgrimes /* 3571573Srgrimes * Disable the brooktree device 3581573Srgrimes */ 3591573Srgrimes OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 3601573Srgrimes OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 3611573Srgrimes 3621573Srgrimes 3631573Srgrimes#ifdef BROOKTREE_IRQ /* from the configuration file */ 3641573Srgrimes old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 3651573Srgrimes pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 3661573Srgrimes new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 3671573Srgrimes printf("bktr%d: attach: irq changed from %d to %d\n", 3681573Srgrimes unit, (old_irq & 0xff), (new_irq & 0xff)); 3691573Srgrimes#endif 3701573Srgrimes 3711573Srgrimes /* 3721573Srgrimes * Allocate our interrupt. 3731573Srgrimes */ 3741573Srgrimes bktr->irq_rid = 0; 3751573Srgrimes bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 3761573Srgrimes &bktr->irq_rid, RF_SHAREABLE | RF_ACTIVE); 3771573Srgrimes if (bktr->res_irq == NULL) { 3781573Srgrimes device_printf(dev, "could not map interrupt\n"); 3791573Srgrimes error = ENXIO; 3801573Srgrimes goto fail; 3811573Srgrimes } 3821573Srgrimes 3831573Srgrimes error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 3841573Srgrimes NULL, bktr_intr, bktr, &bktr->res_ih); 3851573Srgrimes if (error) { 3861573Srgrimes device_printf(dev, "could not setup irq\n"); 3871573Srgrimes goto fail; 3881573Srgrimes 3891573Srgrimes } 3901573Srgrimes 3911573Srgrimes 3921573Srgrimes /* Update the Device Control Register */ 3931573Srgrimes /* on Bt878 and Bt879 cards */ 3941573Srgrimes fun = pci_read_config( dev, 0x40, 2); 3951573Srgrimes fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 3961573Srgrimes 3971573Srgrimes#if defined( BKTR_430_FX_MODE ) 3981573Srgrimes if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 3991573Srgrimes fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 4001573Srgrimes#endif 4011573Srgrimes 4021573Srgrimes#if defined( BKTR_SIS_VIA_MODE ) 4031573Srgrimes if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 4041573Srgrimes fun = fun | 4; /* Enable SiS/VIA compatibility mode (useful for 4051573Srgrimes OPTi chipset motherboards too */ 4061573Srgrimes#endif 4071573Srgrimes pci_write_config(dev, 0x40, fun, 2); 4081573Srgrimes 4091573Srgrimes#if defined(BKTR_USE_FREEBSD_SMBUS) 4101573Srgrimes if (bt848_i2c_attach(dev)) 4111573Srgrimes printf("bktr%d: i2c_attach: can't attach\n", unit); 4121573Srgrimes#endif 4131573Srgrimes 4141573Srgrimes/* 4151573Srgrimes * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 4161573Srgrimes * you have more than four, then 16 would probably be a better value. 4171573Srgrimes */ 4181573Srgrimes#ifndef BROOKTREE_DEF_LATENCY_VALUE 4191573Srgrimes#define BROOKTREE_DEF_LATENCY_VALUE 10 4201573Srgrimes#endif 4211573Srgrimes latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 4221573Srgrimes latency = (latency >> 8) & 0xff; 4231573Srgrimes if ( bootverbose ) { 4241573Srgrimes if (latency) 4251573Srgrimes printf("brooktree%d: PCI bus latency is", unit); 4261573Srgrimes else 4271573Srgrimes printf("brooktree%d: PCI bus latency was 0 changing to", 4281573Srgrimes unit); 4291573Srgrimes } 4301573Srgrimes if ( !latency ) { 4311573Srgrimes latency = BROOKTREE_DEF_LATENCY_VALUE; 4321573Srgrimes pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 4331573Srgrimes } 4341573Srgrimes if ( bootverbose ) { 4351573Srgrimes printf(" %d.\n", (int) latency); 4361573Srgrimes } 4371573Srgrimes 4381573Srgrimes /* read the pci device id and revision id */ 4391573Srgrimes fun = pci_get_devid(dev); 4401573Srgrimes rev = pci_get_revid(dev); 4411573Srgrimes 4421573Srgrimes /* call the common attach code */ 4431573Srgrimes common_bktr_attach( bktr, unit, fun, rev ); 4441573Srgrimes 4451573Srgrimes /* make the device entries */ 4461573Srgrimes bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 4471573Srgrimes 0, 0, 0444, "bktr%d", unit); 4481573Srgrimes bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 4491573Srgrimes 0, 0, 0444, "tuner%d", unit); 4501573Srgrimes bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 4511573Srgrimes 0, 0, 0444, "vbi%d" , unit); 4521573Srgrimes 4531573Srgrimes 4541573Srgrimes /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 4551573Srgrimes /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 4561573Srgrimes#if (__FreeBSD_version >=500000) 4571573Srgrimes if (unit == 0) { 4581573Srgrimes bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 4591573Srgrimes bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 4601573Srgrimes bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 4611573Srgrimes } 4621573Srgrimes#endif 4631573Srgrimes 4641573Srgrimes return 0; 4651573Srgrimes 4661573Srgrimesfail: 4671573Srgrimes if (bktr->res_irq) 4681573Srgrimes bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 4691573Srgrimes if (bktr->res_mem) 4701573Srgrimes bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 4711573Srgrimes return error; 4721573Srgrimes 4731573Srgrimes} 4741573Srgrimes 4751573Srgrimes/* 4761573Srgrimes * the detach routine. 4771573Srgrimes */ 4781573Srgrimesstatic int 4791573Srgrimesbktr_detach( device_t dev ) 4801573Srgrimes{ 4811573Srgrimes struct bktr_softc *bktr = device_get_softc(dev); 4821573Srgrimes 4831573Srgrimes#ifdef BKTR_NEW_MSP34XX_DRIVER 4841573Srgrimes /* Disable the soundchip and kernel thread */ 4851573Srgrimes if (bktr->msp3400c_info != NULL) 4861573Srgrimes msp_detach(bktr); 4871573Srgrimes#endif 4881573Srgrimes 4891573Srgrimes /* Disable the brooktree device */ 4901573Srgrimes OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 4911573Srgrimes OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 4921573Srgrimes 4931573Srgrimes#if defined(BKTR_USE_FREEBSD_SMBUS) 4941573Srgrimes if (bt848_i2c_detach(dev)) 4951573Srgrimes printf("bktr%d: i2c_attach: can't attach\n", 4961573Srgrimes device_get_unit(dev)); 4971573Srgrimes#endif 4981573Srgrimes#ifdef USE_VBIMUTEX 4991573Srgrimes mtx_destroy(&bktr->vbimutex); 5001573Srgrimes#endif 5011573Srgrimes 5021573Srgrimes /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 5031573Srgrimes /* The memory is retained by the bktr_mem module so we can unload and */ 5041573Srgrimes /* then reload the main bktr driver module */ 5051573Srgrimes 5061573Srgrimes /* Unregister the /dev/bktrN, tunerN and vbiN devices, 5071573Srgrimes * the aliases for unit 0 are automatically destroyed */ 5081573Srgrimes destroy_dev(bktr->vbidev); 5091573Srgrimes destroy_dev(bktr->tunerdev); 5101573Srgrimes destroy_dev(bktr->bktrdev); 5111573Srgrimes 5121573Srgrimes /* 5131573Srgrimes * Deallocate resources. 5141573Srgrimes */ 5151573Srgrimes bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 5161573Srgrimes bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 5171573Srgrimes bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 5181573Srgrimes 5191573Srgrimes return 0; 5201573Srgrimes} 5211573Srgrimes 5221573Srgrimes/* 5231573Srgrimes * the shutdown routine. 5241573Srgrimes */ 5251573Srgrimesstatic int 5261573Srgrimesbktr_shutdown( device_t dev ) 5271573Srgrimes{ 5281573Srgrimes struct bktr_softc *bktr = device_get_softc(dev); 5291573Srgrimes 5301573Srgrimes /* Disable the brooktree device */ 5311573Srgrimes OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 5321573Srgrimes OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 5331573Srgrimes 5341573Srgrimes return 0; 5351573Srgrimes} 5361573Srgrimes 5371573Srgrimes 5381573Srgrimes/* 5391573Srgrimes * Special Memory Allocation 5401573Srgrimes */ 5411573Srgrimesvm_offset_t 5421573Srgrimesget_bktr_mem( int unit, unsigned size ) 5431573Srgrimes{ 5441573Srgrimes vm_offset_t addr = 0; 5451573Srgrimes 5461573Srgrimes addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 5471573Srgrimes 0xffffffff, 1<<24, 0); 5481573Srgrimes if (addr == 0) 5491573Srgrimes addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 5501573Srgrimes 0xffffffff, PAGE_SIZE, 0); 5511573Srgrimes if (addr == 0) { 5521573Srgrimes printf("bktr%d: Unable to allocate %d bytes of memory.\n", 5531573Srgrimes unit, size); 5541573Srgrimes } 5551573Srgrimes 5561573Srgrimes return( addr ); 5571573Srgrimes} 5581573Srgrimes 5591573Srgrimes 5601573Srgrimes/*--------------------------------------------------------- 5611573Srgrimes** 5621573Srgrimes** BrookTree 848 character device driver routines 5631573Srgrimes** 5641573Srgrimes**--------------------------------------------------------- 5651573Srgrimes*/ 5661573Srgrimes 5671573Srgrimes#define VIDEO_DEV 0x00 5681573Srgrimes#define TUNER_DEV 0x01 5691573Srgrimes#define VBI_DEV 0x02 5701573Srgrimes 5711573Srgrimes#define UNIT(x) ((x) & 0x0f) 5721573Srgrimes#define FUNCTION(x) (x >> 4) 5731573Srgrimes 5741573Srgrimes/* 5751573Srgrimes * 5761573Srgrimes */ 5771573Srgrimesstatic int 5781573Srgrimesbktr_open( struct cdev *dev, int flags, int fmt, struct thread *td ) 5791573Srgrimes{ 5801573Srgrimes bktr_ptr_t bktr; 5811573Srgrimes int unit; 5821573Srgrimes int result; 5831573Srgrimes 5841573Srgrimes unit = UNIT( dev2unit(dev) ); 5851573Srgrimes 5861573Srgrimes /* Get the device data */ 5871573Srgrimes bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 5881573Srgrimes if (bktr == NULL) { 5891573Srgrimes /* the device is no longer valid/functioning */ 5901573Srgrimes return (ENXIO); 5911573Srgrimes } 5921573Srgrimes 5931573Srgrimes if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 5941573Srgrimes return( ENXIO ); 5951573Srgrimes 5961573Srgrimes /* Record that the device is now busy */ 5971573Srgrimes device_busy(devclass_get_device(bktr_devclass, unit)); 5981573Srgrimes 5991573Srgrimes 6001573Srgrimes if (bt848_card != -1) { 6011573Srgrimes if ((bt848_card >> 8 == unit ) && 6021573Srgrimes ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 6031573Srgrimes if ( bktr->bt848_card != (bt848_card & 0xff) ) { 6041573Srgrimes bktr->bt848_card = (bt848_card & 0xff); 6051573Srgrimes probeCard(bktr, FALSE, unit); 6061573Srgrimes } 6071573Srgrimes } 6081573Srgrimes } 6091573Srgrimes 6101573Srgrimes if (bt848_tuner != -1) { 6111573Srgrimes if ((bt848_tuner >> 8 == unit ) && 6121573Srgrimes ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 6131573Srgrimes if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 6141573Srgrimes bktr->bt848_tuner = (bt848_tuner & 0xff); 6151573Srgrimes probeCard(bktr, FALSE, unit); 6161573Srgrimes } 6171573Srgrimes } 6181573Srgrimes } 6191573Srgrimes 6201573Srgrimes if (bt848_reverse_mute != -1) { 6211573Srgrimes if ((bt848_reverse_mute >> 8) == unit ) { 6221573Srgrimes bktr->reverse_mute = bt848_reverse_mute & 0xff; 6231573Srgrimes } 6241573Srgrimes } 6251573Srgrimes 6261573Srgrimes if (bt848_slow_msp_audio != -1) { 6271573Srgrimes if ((bt848_slow_msp_audio >> 8) == unit ) { 6281573Srgrimes bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 6291573Srgrimes } 6301573Srgrimes } 6311573Srgrimes 6321573Srgrimes#ifdef BKTR_NEW_MSP34XX_DRIVER 6331573Srgrimes if (bt848_stereo_once != 0) { 6341573Srgrimes if ((bt848_stereo_once >> 8) == unit ) { 6351573Srgrimes bktr->stereo_once = (bt848_stereo_once & 0xff); 6361573Srgrimes } 6371573Srgrimes } 6381573Srgrimes 6391573Srgrimes if (bt848_amsound != -1) { 6401573Srgrimes if ((bt848_amsound >> 8) == unit ) { 6411573Srgrimes bktr->amsound = (bt848_amsound & 0xff); 6421573Srgrimes } 6431573Srgrimes } 6441573Srgrimes 6451573Srgrimes if (bt848_dolby != -1) { 6461573Srgrimes if ((bt848_dolby >> 8) == unit ) { 6471573Srgrimes bktr->dolby = (bt848_dolby & 0xff); 6481573Srgrimes } 6491573Srgrimes } 6501573Srgrimes#endif 6511573Srgrimes 6521573Srgrimes switch ( FUNCTION( dev2unit(dev) ) ) { 6531573Srgrimes case VIDEO_DEV: 6541573Srgrimes result = video_open( bktr ); 6551573Srgrimes break; 6561573Srgrimes case TUNER_DEV: 6571573Srgrimes result = tuner_open( bktr ); 6581573Srgrimes break; 6591573Srgrimes case VBI_DEV: 6601573Srgrimes result = vbi_open( bktr ); 6611573Srgrimes break; 6621573Srgrimes default: 6631573Srgrimes result = ENXIO; 6641573Srgrimes break; 6651573Srgrimes } 6661573Srgrimes 6671573Srgrimes /* If there was an error opening the device, undo the busy status */ 6681573Srgrimes if (result != 0) 6691573Srgrimes device_unbusy(devclass_get_device(bktr_devclass, unit)); 6701573Srgrimes return( result ); 6711573Srgrimes} 6721573Srgrimes 6731573Srgrimes 6741573Srgrimes/* 6751573Srgrimes * 6761573Srgrimes */ 6771573Srgrimesstatic int 6781573Srgrimesbktr_close( struct cdev *dev, int flags, int fmt, struct thread *td ) 6791573Srgrimes{ 6801573Srgrimes bktr_ptr_t bktr; 6811573Srgrimes int unit; 6821573Srgrimes int result; 6831573Srgrimes 6841573Srgrimes unit = UNIT( dev2unit(dev) ); 6851573Srgrimes 6861573Srgrimes /* Get the device data */ 6871573Srgrimes bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 6881573Srgrimes if (bktr == NULL) { 6891573Srgrimes /* the device is no longer valid/functioning */ 6901573Srgrimes return (ENXIO); 6918870Srgrimes } 6921573Srgrimes 6931573Srgrimes switch ( FUNCTION( dev2unit(dev) ) ) { 6941573Srgrimes case VIDEO_DEV: 6951573Srgrimes result = video_close( bktr ); 6961573Srgrimes break; 6971573Srgrimes case TUNER_DEV: 6981573Srgrimes result = tuner_close( bktr ); 6991573Srgrimes break; 7001573Srgrimes case VBI_DEV: 7011573Srgrimes result = vbi_close( bktr ); 7021573Srgrimes break; 7031573Srgrimes default: 7041573Srgrimes return (ENXIO); 7051573Srgrimes break; 7061573Srgrimes } 7071573Srgrimes 7081573Srgrimes device_unbusy(devclass_get_device(bktr_devclass, unit)); 7091573Srgrimes return( result ); 7101573Srgrimes} 7111573Srgrimes 7121573Srgrimes 7131573Srgrimes/* 7141573Srgrimes * 7151573Srgrimes */ 7161573Srgrimesstatic int 7171573Srgrimesbktr_read( struct cdev *dev, struct uio *uio, int ioflag ) 7181573Srgrimes{ 7191573Srgrimes bktr_ptr_t bktr; 7201573Srgrimes int unit; 7211573Srgrimes 7221573Srgrimes unit = UNIT(dev2unit(dev)); 7231573Srgrimes 7241573Srgrimes /* Get the device data */ 7251573Srgrimes bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 7261573Srgrimes if (bktr == NULL) { 7271573Srgrimes /* the device is no longer valid/functioning */ 7281573Srgrimes return (ENXIO); 7291573Srgrimes } 7301573Srgrimes 7311573Srgrimes switch ( FUNCTION( dev2unit(dev) ) ) { 7321573Srgrimes case VIDEO_DEV: 7331573Srgrimes return( video_read( bktr, unit, dev, uio ) ); 7341573Srgrimes case VBI_DEV: 7351573Srgrimes return( vbi_read( bktr, uio, ioflag ) ); 7361573Srgrimes } 7371573Srgrimes return( ENXIO ); 7381573Srgrimes} 7391573Srgrimes 7401573Srgrimes 7411573Srgrimes/* 7421573Srgrimes * 7431573Srgrimes */ 7441573Srgrimesstatic int 7451573Srgrimesbktr_write( struct cdev *dev, struct uio *uio, int ioflag ) 7461573Srgrimes{ 7471573Srgrimes return( EINVAL ); /* XXX or ENXIO ? */ 7481573Srgrimes} 7491573Srgrimes 7501573Srgrimes 7511573Srgrimes/* 7521573Srgrimes * 7531573Srgrimes */ 7541573Srgrimesstatic int 7551573Srgrimesbktr_ioctl( struct cdev *dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 7561573Srgrimes{ 7571573Srgrimes bktr_ptr_t bktr; 7581573Srgrimes int unit; 7591573Srgrimes 7601573Srgrimes unit = UNIT(dev2unit(dev)); 7611573Srgrimes 7621573Srgrimes /* Get the device data */ 7631573Srgrimes bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 7641573Srgrimes if (bktr == NULL) { 7651573Srgrimes /* the device is no longer valid/functioning */ 7661573Srgrimes return (ENXIO); 7671573Srgrimes } 7681573Srgrimes 7691573Srgrimes#ifdef BKTR_GPIO_ACCESS 7701573Srgrimes if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN && 7711573Srgrimes cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA && 7721573Srgrimes cmd != BT848_GPIO_SET_DATA) /* no frame buffer allocated (ioctl failed) */ 7731573Srgrimes return( ENOMEM ); 7741573Srgrimes#else 7751573Srgrimes if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 7761573Srgrimes return( ENOMEM ); 7771573Srgrimes#endif 7781573Srgrimes 7791573Srgrimes switch ( FUNCTION( dev2unit(dev) ) ) { 7801573Srgrimes case VIDEO_DEV: 7811573Srgrimes return( video_ioctl( bktr, unit, cmd, arg, td ) ); 7821573Srgrimes case TUNER_DEV: 7831573Srgrimes return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 7841573Srgrimes } 7851573Srgrimes 7861573Srgrimes return( ENXIO ); 7871573Srgrimes} 7881573Srgrimes 7891573Srgrimes 7901573Srgrimes/* 7911573Srgrimes * 7921573Srgrimes */ 7931573Srgrimesstatic int 7941573Srgrimesbktr_mmap( struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, 7951573Srgrimes int nprot, vm_memattr_t *memattr ) 7961573Srgrimes{ 7971573Srgrimes int unit; 7981573Srgrimes bktr_ptr_t bktr; 7991573Srgrimes 8001573Srgrimes unit = UNIT(dev2unit(dev)); 8011573Srgrimes 8021573Srgrimes if (FUNCTION(dev2unit(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 8031573Srgrimes return( -1 ); 8041573Srgrimes 8051573Srgrimes /* Get the device data */ 8061573Srgrimes bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 8071573Srgrimes if (bktr == NULL) { 8081573Srgrimes /* the device is no longer valid/functioning */ 8091573Srgrimes return (ENXIO); 8101573Srgrimes } 8111573Srgrimes 8121573Srgrimes if (nprot & PROT_EXEC) 8131573Srgrimes return( -1 ); 8141573Srgrimes 8151573Srgrimes if (offset < 0) 8161573Srgrimes return( -1 ); 8171573Srgrimes 8181573Srgrimes if (offset >= bktr->alloc_pages * PAGE_SIZE) 8191573Srgrimes return( -1 ); 8201573Srgrimes 8211573Srgrimes *paddr = vtophys(bktr->bigbuf) + offset; 8221573Srgrimes return( 0 ); 8231573Srgrimes} 8241573Srgrimes 8251573Srgrimesstatic int 8261573Srgrimesbktr_poll( struct cdev *dev, int events, struct thread *td) 8271573Srgrimes{ 8281573Srgrimes int unit; 8291573Srgrimes bktr_ptr_t bktr; 8301573Srgrimes int revents = 0; 8311573Srgrimes DECLARE_INTR_MASK(s); 8321573Srgrimes 8331573Srgrimes unit = UNIT(dev2unit(dev)); 8341573Srgrimes 8351573Srgrimes /* Get the device data */ 8361573Srgrimes bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 8371573Srgrimes if (bktr == NULL) { 8381573Srgrimes /* the device is no longer valid/functioning */ 8391573Srgrimes return (ENXIO); 8401573Srgrimes } 8411573Srgrimes 8421573Srgrimes LOCK_VBI(bktr); 8431573Srgrimes DISABLE_INTR(s); 8441573Srgrimes 8451573Srgrimes if (events & (POLLIN | POLLRDNORM)) { 8461573Srgrimes 8471573Srgrimes switch ( FUNCTION( dev2unit(dev) ) ) { 8481573Srgrimes case VBI_DEV: 8491573Srgrimes if(bktr->vbisize == 0) 8501573Srgrimes selrecord(td, &bktr->vbi_select); 8511573Srgrimes else 8521573Srgrimes revents |= events & (POLLIN | POLLRDNORM); 8531573Srgrimes break; 8541573Srgrimes } 8551573Srgrimes } 8561573Srgrimes 8571573Srgrimes ENABLE_INTR(s); 8581573Srgrimes UNLOCK_VBI(bktr); 8591573Srgrimes 8601573Srgrimes return (revents); 8611573Srgrimes} 8621573Srgrimes 8631573Srgrimes/*****************/ 8641573Srgrimes/* *** BSDI *** */ 8651573Srgrimes/*****************/ 8661573Srgrimes 8671573Srgrimes#if defined(__bsdi__) 8681573Srgrimes#endif /* __bsdi__ BSDI specific kernel interface routines */ 8691573Srgrimes 8701573Srgrimes 8711573Srgrimes/*****************************/ 8721573Srgrimes/* *** OpenBSD / NetBSD *** */ 8731573Srgrimes/*****************************/ 8741573Srgrimes#if defined(__NetBSD__) || defined(__OpenBSD__) 8751573Srgrimes 8761573Srgrimes#define IPL_VIDEO IPL_BIO /* XXX */ 8771573Srgrimes 8781573Srgrimesstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 8791573Srgrimes 8801573Srgrimes#define bktr_open bktropen 8811573Srgrimes#define bktr_close bktrclose 8821573Srgrimes#define bktr_read bktrread 8831573Srgrimes#define bktr_write bktrwrite 8841573Srgrimes#define bktr_ioctl bktrioctl 8851573Srgrimes#define bktr_mmap bktrmmap 8861573Srgrimes 8871573Srgrimesvm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 8881573Srgrimes vm_offset_t, vm_offset_t); 8891573Srgrimes 8901573Srgrimes#if defined(__OpenBSD__) 8911573Srgrimesstatic int bktr_probe(struct device *, void *, void *); 8921573Srgrimes#else 8931573Srgrimesstatic int bktr_probe(struct device *, struct cfdata *, void *); 8941573Srgrimes#endif 8951573Srgrimesstatic void bktr_attach(struct device *, struct device *, void *); 8961573Srgrimes 8971573Srgrimesstruct cfattach bktr_ca = { 8981573Srgrimes sizeof(struct bktr_softc), bktr_probe, bktr_attach 8991573Srgrimes}; 9001573Srgrimes 9011573Srgrimes#if defined(__NetBSD__) 9021573Srgrimesextern struct cfdriver bktr_cd; 9031573Srgrimes#else 9041573Srgrimesstruct cfdriver bktr_cd = { 9051573Srgrimes NULL, "bktr", DV_DULL 9061573Srgrimes}; 9071573Srgrimes#endif 9081573Srgrimes 9091573Srgrimesint 9101573Srgrimesbktr_probe(parent, match, aux) 9111573Srgrimes struct device *parent; 9121573Srgrimes#if defined(__OpenBSD__) 9131573Srgrimes void *match; 9141573Srgrimes#else 9151573Srgrimes struct cfdata *match; 9161573Srgrimes#endif 9171573Srgrimes void *aux; 9181573Srgrimes{ 9191573Srgrimes struct pci_attach_args *pa = aux; 9201573Srgrimes 9211573Srgrimes if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 9221573Srgrimes (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 9231573Srgrimes PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 9241573Srgrimes PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 9251573Srgrimes PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 9261573Srgrimes return 1; 9271573Srgrimes 9281573Srgrimes return 0; 9291573Srgrimes} 9301573Srgrimes 9311573Srgrimes 9321573Srgrimes/* 9331573Srgrimes * the attach routine. 9341573Srgrimes */ 9351573Srgrimesstatic void 9361573Srgrimesbktr_attach(struct device *parent, struct device *self, void *aux) 9371573Srgrimes{ 9381573Srgrimes bktr_ptr_t bktr; 9391573Srgrimes u_long latency; 9401573Srgrimes u_long fun; 9411573Srgrimes unsigned int rev; 9421573Srgrimes 9431573Srgrimes#if defined(__OpenBSD__) 9441573Srgrimes struct pci_attach_args *pa = aux; 945 pci_chipset_tag_t pc = pa->pa_pc; 946 947 pci_intr_handle_t ih; 948 const char *intrstr; 949 int retval; 950 int unit; 951 952 bktr = (bktr_ptr_t)self; 953 unit = bktr->bktr_dev.dv_unit; 954 955 bktr->pc = pa->pa_pc; 956 bktr->tag = pa->pa_tag; 957 bktr->dmat = pa->pa_dmat; 958 959 /* 960 * map memory 961 */ 962 bktr->memt = pa->pa_memt; 963 retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 964 &bktr->phys_base, &bktr->obmemsz, NULL); 965 if (!retval) 966 retval = bus_space_map(pa->pa_memt, bktr->phys_base, 967 bktr->obmemsz, 0, &bktr->memh); 968 if (retval) { 969 printf(": couldn't map memory\n"); 970 return; 971 } 972 973 974 /* 975 * map interrupt 976 */ 977 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 978 pa->pa_intrline, &ih)) { 979 printf(": couldn't map interrupt\n"); 980 return; 981 } 982 intrstr = pci_intr_string(pa->pa_pc, ih); 983 984 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 985 bktr_intr, bktr, bktr->bktr_dev.dv_xname); 986 if (bktr->ih == NULL) { 987 printf(": couldn't establish interrupt"); 988 if (intrstr != NULL) 989 printf(" at %s", intrstr); 990 printf("\n"); 991 return; 992 } 993 994 if (intrstr != NULL) 995 printf(": %s\n", intrstr); 996#endif /* __OpenBSD__ */ 997 998#if defined(__NetBSD__) 999 struct pci_attach_args *pa = aux; 1000 pci_intr_handle_t ih; 1001 const char *intrstr; 1002 int retval; 1003 int unit; 1004 1005 bktr = (bktr_ptr_t)self; 1006 unit = bktr->bktr_dev.dv_unit; 1007 bktr->dmat = pa->pa_dmat; 1008 1009 printf("\n"); 1010 1011 /* 1012 * map memory 1013 */ 1014 retval = pci_mapreg_map(pa, PCI_MAPREG_START, 1015 PCI_MAPREG_TYPE_MEM 1016 | PCI_MAPREG_MEM_TYPE_32BIT, 0, 1017 &bktr->memt, &bktr->memh, NULL, 1018 &bktr->obmemsz); 1019 DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 1020 bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 1021 if (retval) { 1022 printf("%s: couldn't map memory\n", bktr_name(bktr)); 1023 return; 1024 } 1025 1026 /* 1027 * Disable the brooktree device 1028 */ 1029 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 1030 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 1031 1032 /* 1033 * map interrupt 1034 */ 1035 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 1036 pa->pa_intrline, &ih)) { 1037 printf("%s: couldn't map interrupt\n", 1038 bktr_name(bktr)); 1039 return; 1040 } 1041 intrstr = pci_intr_string(pa->pa_pc, ih); 1042 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 1043 bktr_intr, bktr); 1044 if (bktr->ih == NULL) { 1045 printf("%s: couldn't establish interrupt", 1046 bktr_name(bktr)); 1047 if (intrstr != NULL) 1048 printf(" at %s", intrstr); 1049 printf("\n"); 1050 return; 1051 } 1052 if (intrstr != NULL) 1053 printf("%s: interrupting at %s\n", bktr_name(bktr), 1054 intrstr); 1055#endif /* __NetBSD__ */ 1056 1057/* 1058 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 1059 * you have more than four, then 16 would probably be a better value. 1060 */ 1061#ifndef BROOKTREE_DEF_LATENCY_VALUE 1062#define BROOKTREE_DEF_LATENCY_VALUE 10 1063#endif 1064 latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 1065 latency = (latency >> 8) & 0xff; 1066 1067 if (!latency) { 1068 if (bootverbose) { 1069 printf("%s: PCI bus latency was 0 changing to %d", 1070 bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 1071 } 1072 latency = BROOKTREE_DEF_LATENCY_VALUE; 1073 pci_conf_write(pa->pa_pc, pa->pa_tag, 1074 PCI_LATENCY_TIMER, latency<<8); 1075 } 1076 1077 1078 /* Enabled Bus Master 1079 XXX: check if all old DMA is stopped first (e.g. after warm 1080 boot) */ 1081 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1082 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 1083 fun | PCI_COMMAND_MASTER_ENABLE); 1084 1085 /* read the pci id and determine the card type */ 1086 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 1087 rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 1088 1089 common_bktr_attach(bktr, unit, fun, rev); 1090} 1091 1092 1093/* 1094 * Special Memory Allocation 1095 */ 1096vm_offset_t 1097get_bktr_mem(bktr, dmapp, size) 1098 bktr_ptr_t bktr; 1099 bus_dmamap_t *dmapp; 1100 unsigned int size; 1101{ 1102 bus_dma_tag_t dmat = bktr->dmat; 1103 bus_dma_segment_t seg; 1104 bus_size_t align; 1105 int rseg; 1106 caddr_t kva; 1107 1108 /* 1109 * Allocate a DMA area 1110 */ 1111 align = 1 << 24; 1112 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1113 &rseg, BUS_DMA_NOWAIT)) { 1114 align = PAGE_SIZE; 1115 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1116 &rseg, BUS_DMA_NOWAIT)) { 1117 printf("%s: Unable to dmamem_alloc of %d bytes\n", 1118 bktr_name(bktr), size); 1119 return 0; 1120 } 1121 } 1122 if (bus_dmamem_map(dmat, &seg, rseg, size, 1123 &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 1124 printf("%s: Unable to dmamem_map of %d bytes\n", 1125 bktr_name(bktr), size); 1126 bus_dmamem_free(dmat, &seg, rseg); 1127 return 0; 1128 } 1129#ifdef __OpenBSD__ 1130 bktr->dm_mapsize = size; 1131#endif 1132 /* 1133 * Create and locd the DMA map for the DMA area 1134 */ 1135 if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 1136 printf("%s: Unable to dmamap_create of %d bytes\n", 1137 bktr_name(bktr), size); 1138 bus_dmamem_unmap(dmat, kva, size); 1139 bus_dmamem_free(dmat, &seg, rseg); 1140 return 0; 1141 } 1142 if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 1143 printf("%s: Unable to dmamap_load of %d bytes\n", 1144 bktr_name(bktr), size); 1145 bus_dmamem_unmap(dmat, kva, size); 1146 bus_dmamem_free(dmat, &seg, rseg); 1147 bus_dmamap_destroy(dmat, *dmapp); 1148 return 0; 1149 } 1150 return (vm_offset_t)kva; 1151} 1152 1153void 1154free_bktr_mem(bktr, dmap, kva) 1155 bktr_ptr_t bktr; 1156 bus_dmamap_t dmap; 1157 vm_offset_t kva; 1158{ 1159 bus_dma_tag_t dmat = bktr->dmat; 1160 1161#ifdef __NetBSD__ 1162 bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 1163#else 1164 bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 1165#endif 1166 bus_dmamem_free(dmat, dmap->dm_segs, 1); 1167 bus_dmamap_destroy(dmat, dmap); 1168} 1169 1170 1171/*--------------------------------------------------------- 1172** 1173** BrookTree 848 character device driver routines 1174** 1175**--------------------------------------------------------- 1176*/ 1177 1178 1179#define VIDEO_DEV 0x00 1180#define TUNER_DEV 0x01 1181#define VBI_DEV 0x02 1182 1183#define UNIT(x) (dev2unit((x) & 0x0f)) 1184#define FUNCTION(x) (dev2unit((x >> 4) & 0x0f)) 1185 1186/* 1187 * 1188 */ 1189int 1190bktr_open(dev_t dev, int flags, int fmt, struct thread *td) 1191{ 1192 bktr_ptr_t bktr; 1193 int unit; 1194 1195 unit = UNIT(dev); 1196 1197 /* unit out of range */ 1198 if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 1199 return(ENXIO); 1200 1201 bktr = bktr_cd.cd_devs[unit]; 1202 1203 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 1204 return(ENXIO); 1205 1206 switch (FUNCTION(dev)) { 1207 case VIDEO_DEV: 1208 return(video_open(bktr)); 1209 case TUNER_DEV: 1210 return(tuner_open(bktr)); 1211 case VBI_DEV: 1212 return(vbi_open(bktr)); 1213 } 1214 1215 return(ENXIO); 1216} 1217 1218 1219/* 1220 * 1221 */ 1222int 1223bktr_close(dev_t dev, int flags, int fmt, struct thread *td) 1224{ 1225 bktr_ptr_t bktr; 1226 int unit; 1227 1228 unit = UNIT(dev); 1229 1230 bktr = bktr_cd.cd_devs[unit]; 1231 1232 switch (FUNCTION(dev)) { 1233 case VIDEO_DEV: 1234 return(video_close(bktr)); 1235 case TUNER_DEV: 1236 return(tuner_close(bktr)); 1237 case VBI_DEV: 1238 return(vbi_close(bktr)); 1239 } 1240 1241 return(ENXIO); 1242} 1243 1244/* 1245 * 1246 */ 1247int 1248bktr_read(dev_t dev, struct uio *uio, int ioflag) 1249{ 1250 bktr_ptr_t bktr; 1251 int unit; 1252 1253 unit = UNIT(dev); 1254 1255 bktr = bktr_cd.cd_devs[unit]; 1256 1257 switch (FUNCTION(dev)) { 1258 case VIDEO_DEV: 1259 return(video_read(bktr, unit, dev, uio)); 1260 case VBI_DEV: 1261 return(vbi_read(bktr, uio, ioflag)); 1262 } 1263 1264 return(ENXIO); 1265} 1266 1267 1268/* 1269 * 1270 */ 1271int 1272bktr_write(dev_t dev, struct uio *uio, int ioflag) 1273{ 1274 /* operation not supported */ 1275 return(EOPNOTSUPP); 1276} 1277 1278/* 1279 * 1280 */ 1281int 1282bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 1283{ 1284 bktr_ptr_t bktr; 1285 int unit; 1286 1287 unit = UNIT(dev); 1288 1289 bktr = bktr_cd.cd_devs[unit]; 1290 1291 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 1292 return(ENOMEM); 1293 1294 switch (FUNCTION(dev)) { 1295 case VIDEO_DEV: 1296 return(video_ioctl(bktr, unit, cmd, arg, pr)); 1297 case TUNER_DEV: 1298 return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 1299 } 1300 1301 return(ENXIO); 1302} 1303 1304/* 1305 * 1306 */ 1307paddr_t 1308bktr_mmap(dev_t dev, off_t offset, int nprot) 1309{ 1310 int unit; 1311 bktr_ptr_t bktr; 1312 1313 unit = UNIT(dev); 1314 1315 if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 1316 return(-1); 1317 1318 bktr = bktr_cd.cd_devs[unit]; 1319 1320 if ((vaddr_t)offset < 0) 1321 return(-1); 1322 1323 if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 1324 return(-1); 1325 1326#ifdef __NetBSD__ 1327 return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 1328 (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 1329#else 1330 return(i386_btop(vtophys(bktr->bigbuf) + offset)); 1331#endif 1332} 1333 1334#endif /* __NetBSD__ || __OpenBSD__ */ 1335