bktr_os.c revision 119418
1233294Sstas/*- 2102644Snectar * 1. Redistributions of source code must retain the 355682Smarkm * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 4142403Snectar * All rights reserved. 5233294Sstas * 6233294Sstas * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1. Redistributions of source code must retain the above copyright 1055682Smarkm * notice, this list of conditions and the following disclaimer. 1155682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1255682Smarkm * notice, this list of conditions and the following disclaimer in the 1355682Smarkm * documentation and/or other materials provided with the distribution. 1455682Smarkm * 3. All advertising materials mentioning features or use of this software 1555682Smarkm * must display the following acknowledgement: 1690926Snectar * This product includes software developed by Amancio Hasty and 1790926Snectar * Roger Hardiman 18233294Sstas * 4. The name of the author may not be used to endorse or promote products 1990926Snectar * derived from this software without specific prior written permission. 20233294Sstas * 2190926Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22233294Sstas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2355682Smarkm * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2455682Smarkm * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2555682Smarkm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26233294Sstas * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2755682Smarkm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29102644Snectar * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30102644Snectar * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31102644Snectar * POSSIBILITY OF SUCH DAMAGE. 32127808Snectar */ 3390926Snectar 34127808Snectar#include <sys/cdefs.h> 3555682Smarkm__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_os.c 119418 2003-08-24 17:55:58Z obrien $"); 3655682Smarkm 3755682Smarkm/* 3855682Smarkm * This is part of the Driver for Video Capture Cards (Frame grabbers) 3955682Smarkm * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 4055682Smarkm * chipset. 41178825Sdfr * Copyright Roger Hardiman and Amancio Hasty. 4255682Smarkm * 43142403Snectar * bktr_os : This has all the Operating System dependant code, 44142403Snectar * probe/attach and open/close/ioctl/read/mmap 45178825Sdfr * memory allocation 46142403Snectar * PCI bus interfacing 47142403Snectar */ 48142403Snectar 49142403Snectar#include "opt_bktr.h" /* include any kernel config options */ 50233294Sstas 51142403Snectar#define FIFO_RISC_DISABLED 0 52142403Snectar#define ALL_INTS_DISABLED 0 53142403Snectar 54142403Snectar 55142403Snectar/*******************/ 56142403Snectar/* *** FreeBSD *** */ 57142403Snectar/*******************/ 58142403Snectar#ifdef __FreeBSD__ 59142403Snectar 60142403Snectar#include <sys/param.h> 61142403Snectar#include <sys/systm.h> 62142403Snectar#include <sys/conf.h> 63142403Snectar#include <sys/uio.h> 64142403Snectar#include <sys/kernel.h> 65233294Sstas#include <sys/signalvar.h> 66142403Snectar#include <sys/mman.h> 67142403Snectar#include <sys/poll.h> 68142403Snectar#if __FreeBSD_version >= 500014 69142403Snectar#include <sys/selinfo.h> 70178825Sdfr#else 71142403Snectar#include <sys/select.h> 72142403Snectar#endif 73142403Snectar#include <sys/vnode.h> 74142403Snectar 75142403Snectar#include <vm/vm.h> 76142403Snectar#include <vm/vm_kern.h> 77142403Snectar#include <vm/pmap.h> 78142403Snectar#include <vm/vm_extern.h> 79233294Sstas 80233294Sstas#if (__FreeBSD_version >=400000) 81233294Sstas#include <sys/bus.h> /* used by smbus and newbus */ 82233294Sstas#endif 83233294Sstas 84233294Sstas#if (__FreeBSD_version >=300000) 85178825Sdfr#include <machine/bus_memio.h> /* used by bus space */ 86178825Sdfr#include <machine/bus.h> /* used by bus space and newbus */ 87178825Sdfr#include <sys/bus.h> 88178825Sdfr#endif 89178825Sdfr 90178825Sdfr#if (__FreeBSD_version >=400000) 91178825Sdfr#include <sys/rman.h> /* used by newbus */ 92233294Sstas#include <machine/resource.h> /* used by newbus */ 93142403Snectar#endif 94142403Snectar 95178825Sdfr#if (__FreeBSD_version < 500000) 96142403Snectar#include <machine/clock.h> /* for DELAY */ 97142403Snectar#include <pci/pcivar.h> 98233294Sstas#include <pci/pcireg.h> 99142403Snectar#else 100142403Snectar#include <dev/pci/pcivar.h> 101178825Sdfr#include <dev/pci/pcireg.h> 102233294Sstas#endif 103233294Sstas 104233294Sstas#include <sys/sysctl.h> 105178825Sdfrint bt848_card = -1; 106178825Sdfrint bt848_tuner = -1; 107142403Snectarint bt848_reverse_mute = -1; 108142403Snectarint bt848_format = -1; 109142403Snectarint bt848_slow_msp_audio = -1; 110142403Snectar#ifdef BKTR_NEW_MSP34XX_DRIVER 111142403Snectarint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 112142403Snectarint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 113142403Snectar the autoscan seems work well only with FM... */ 114233294Sstasint bt848_dolby = 0; 115233294Sstas#endif 116233294Sstas 117142403SnectarSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 118142403SnectarSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 119178825SdfrSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 120178825SdfrSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 121178825SdfrSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 122142403SnectarSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 123178825Sdfr#ifdef BKTR_NEW_MSP34XX_DRIVER 124178825SdfrSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 125178825SdfrSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 126178825SdfrSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 127178825Sdfr#endif 128233294Sstas 129233294Sstas#endif /* end freebsd section */ 130233294Sstas 131233294Sstas 132233294Sstas 133233294Sstas/****************/ 134233294Sstas/* *** BSDI *** */ 135233294Sstas/****************/ 136233294Sstas#ifdef __bsdi__ 137233294Sstas#endif /* __bsdi__ */ 138233294Sstas 139233294Sstas 140233294Sstas/**************************/ 141233294Sstas/* *** OpenBSD/NetBSD *** */ 142233294Sstas/**************************/ 143233294Sstas#if defined(__NetBSD__) || defined(__OpenBSD__) 144233294Sstas 145233294Sstas#include <sys/param.h> 146233294Sstas#include <sys/systm.h> 147233294Sstas#include <sys/conf.h> 148233294Sstas#include <sys/uio.h> 149142403Snectar#include <sys/kernel.h> 150142403Snectar#include <sys/signalvar.h> 151142403Snectar#include <sys/mman.h> 152142403Snectar#include <sys/poll.h> 153142403Snectar#include <sys/select.h> 154127808Snectar#include <sys/vnode.h> 15555682Smarkm 15672445Sassar#include <vm/vm.h> 157127808Snectar 158233294Sstas#ifndef __NetBSD__ 159233294Sstas#include <vm/vm_kern.h> 160127808Snectar#include <vm/pmap.h> 161127808Snectar#include <vm/vm_extern.h> 162127808Snectar#endif 16355682Smarkm 16455682Smarkm#include <sys/device.h> 165233294Sstas#include <dev/pci/pcivar.h> 166233294Sstas#include <dev/pci/pcireg.h> 16755682Smarkm#include <dev/pci/pcidevs.h> 16855682Smarkm 16955682Smarkm#define BKTR_DEBUG 170233294Sstas#ifdef BKTR_DEBUG 171127808Snectarint bktr_debug = 0; 17290926Snectar#define DPR(x) (bktr_debug ? printf x : 0) 17372445Sassar#else 174127808Snectar#define DPR(x) 175127808Snectar#endif 176233294Sstas#endif /* __NetBSD__ || __OpenBSD__ */ 17755682Smarkm 178127808Snectar 179233294Sstas#ifdef __NetBSD__ 18090926Snectar#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 181178825Sdfr#include <dev/pci/bktr/bktr_reg.h> 182178825Sdfr#include <dev/pci/bktr/bktr_tuner.h> 18372445Sassar#include <dev/pci/bktr/bktr_card.h> 184233294Sstas#include <dev/pci/bktr/bktr_audio.h> 185233294Sstas#include <dev/pci/bktr/bktr_core.h> 186233294Sstas#include <dev/pci/bktr/bktr_os.h> 187127808Snectar#else /* Traditional location for .h files */ 188127808Snectar#include <machine/ioctl_meteor.h> 189127808Snectar#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 190127808Snectar#include <dev/bktr/bktr_reg.h> 191127808Snectar#include <dev/bktr/bktr_tuner.h> 192233294Sstas#include <dev/bktr/bktr_card.h> 193178825Sdfr#include <dev/bktr/bktr_audio.h> 19455682Smarkm#include <dev/bktr/bktr_core.h> 19572445Sassar#include <dev/bktr/bktr_os.h> 196178825Sdfr 197127808Snectar#if defined(BKTR_USE_FREEBSD_SMBUS) 198127808Snectar#include <dev/bktr/bktr_i2c.h> 199233294Sstas 200233294Sstas#include "iicbb_if.h" 201127808Snectar#include "smbus_if.h" 202127808Snectar#endif 203233294Sstas#endif 204178825Sdfr 205127808Snectar 206127808Snectar/****************************/ 207127808Snectar/* *** FreeBSD 4.x code *** */ 20890926Snectar/****************************/ 209233294Sstas#if (__FreeBSD_version >= 400000) 210127808Snectar 211178825Sdfrstatic int bktr_probe( device_t dev ); 21255682Smarkmstatic int bktr_attach( device_t dev ); 213102644Snectarstatic int bktr_detach( device_t dev ); 214102644Snectarstatic int bktr_shutdown( device_t dev ); 215178825Sdfrstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 216127808Snectar 217127808Snectarstatic device_method_t bktr_methods[] = { 21855682Smarkm /* Device interface */ 21955682Smarkm DEVMETHOD(device_probe, bktr_probe), 22090926Snectar DEVMETHOD(device_attach, bktr_attach), 221127808Snectar DEVMETHOD(device_detach, bktr_detach), 222127808Snectar DEVMETHOD(device_shutdown, bktr_shutdown), 223127808Snectar 224127808Snectar#if defined(BKTR_USE_FREEBSD_SMBUS) 225127808Snectar /* iicbb interface */ 22690926Snectar DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22790926Snectar DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 22890926Snectar DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 229127808Snectar DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 230127808Snectar DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 231127808Snectar DEVMETHOD(iicbb_reset, bti2c_iic_reset), 232127808Snectar 233233294Sstas /* smbus interface */ 234127808Snectar DEVMETHOD(smbus_callback, bti2c_smb_callback), 235127808Snectar DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 236233294Sstas DEVMETHOD(smbus_writew, bti2c_smb_writew), 237178825Sdfr DEVMETHOD(smbus_readb, bti2c_smb_readb), 238127808Snectar#endif 239127808Snectar 240127808Snectar { 0, 0 } 241127808Snectar}; 242127808Snectar 243127808Snectarstatic driver_t bktr_driver = { 244127808Snectar "bktr", 245127808Snectar bktr_methods, 246178825Sdfr sizeof(struct bktr_softc), 247178825Sdfr}; 248178825Sdfr 249178825Sdfrstatic devclass_t bktr_devclass; 250127808Snectar 251127808Snectarstatic d_open_t bktr_open; 25255682Smarkmstatic d_close_t bktr_close; 253127808Snectarstatic d_read_t bktr_read; 254233294Sstasstatic d_write_t bktr_write; 255233294Sstasstatic d_ioctl_t bktr_ioctl; 256127808Snectarstatic d_mmap_t bktr_mmap; 257127808Snectarstatic d_poll_t bktr_poll; 258127808Snectar 259127808Snectar#define CDEV_MAJOR 92 260127808Snectarstatic struct cdevsw bktr_cdevsw = { 26155682Smarkm .d_open = bktr_open, 262127808Snectar .d_close = bktr_close, 263127808Snectar .d_read = bktr_read, 264178825Sdfr .d_write = bktr_write, 265127808Snectar .d_ioctl = bktr_ioctl, 266127808Snectar .d_poll = bktr_poll, 26755682Smarkm .d_mmap = bktr_mmap, 26855682Smarkm .d_name = "bktr", 269127808Snectar .d_maj = CDEV_MAJOR, 270127808Snectar}; 271233294Sstas 272127808SnectarDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 273127808Snectar#if (__FreeBSD_version > 410000) 274233294SstasMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27555682SmarkmMODULE_VERSION(bktr, 1); 27655682Smarkm#endif 277120945Snectar 278127808Snectar 279233294Sstas/* 280178825Sdfr * the boot time probe routine. 281233294Sstas */ 282233294Sstasstatic int 283233294Sstasbktr_probe( device_t dev ) 28455682Smarkm{ 285233294Sstas unsigned int type = pci_get_devid(dev); 286127808Snectar unsigned int rev = pci_get_revid(dev); 287233294Sstas 288233294Sstas if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 28955682Smarkm { 290127808Snectar switch (PCI_PRODUCT(type)) { 291127808Snectar case PCI_PRODUCT_BROOKTREE_BT848: 292127808Snectar if (rev == 0x12) 293127808Snectar device_set_desc(dev, "BrookTree 848A"); 294233294Sstas else 295127808Snectar device_set_desc(dev, "BrookTree 848"); 296127808Snectar return 0; 297233294Sstas case PCI_PRODUCT_BROOKTREE_BT849: 298233294Sstas device_set_desc(dev, "BrookTree 849A"); 299233294Sstas return 0; 300233294Sstas case PCI_PRODUCT_BROOKTREE_BT878: 30155682Smarkm device_set_desc(dev, "BrookTree 878"); 302233294Sstas return 0; 303127808Snectar case PCI_PRODUCT_BROOKTREE_BT879: 304127808Snectar device_set_desc(dev, "BrookTree 879"); 305233294Sstas return 0; 306233294Sstas } 307102644Snectar }; 30855682Smarkm 309178825Sdfr return ENXIO; 31055682Smarkm} 31155682Smarkm 31255682Smarkm 313178825Sdfr/* 31490926Snectar * the attach routine. 31590926Snectar */ 31690926Snectarstatic int 31790926Snectarbktr_attach( device_t dev ) 31855682Smarkm{ 319178825Sdfr u_long latency; 320178825Sdfr u_long fun; 321178825Sdfr u_long val; 322178825Sdfr unsigned int rev; 323178825Sdfr unsigned int unit; 324233294Sstas int error = 0; 325127808Snectar#ifdef BROOKTREE_IRQ 326233294Sstas u_long old_irq, new_irq; 327233294Sstas#endif 328127808Snectar 329233294Sstas struct bktr_softc *bktr = device_get_softc(dev); 330178825Sdfr 331178825Sdfr unit = device_get_unit(dev); 332127808Snectar 333127808Snectar /* build the device name for bktr_name() */ 334127808Snectar snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 335127808Snectar 336127808Snectar /* 337127808Snectar * Enable bus mastering and Memory Mapped device 338178825Sdfr */ 339127808Snectar val = pci_read_config(dev, PCIR_COMMAND, 4); 340178825Sdfr val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 341178825Sdfr pci_write_config(dev, PCIR_COMMAND, val, 4); 342102644Snectar 343102644Snectar /* 344102644Snectar * Map control/status registers. 345178825Sdfr */ 346127808Snectar bktr->mem_rid = PCIR_MAPS; 347127808Snectar bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 348127808Snectar 0, ~0, 1, RF_ACTIVE); 349127808Snectar 350127808Snectar 351127808Snectar if (!bktr->res_mem) { 352178825Sdfr device_printf(dev, "could not map memory\n"); 353127808Snectar error = ENXIO; 354127808Snectar goto fail; 35572445Sassar } 356127808Snectar bktr->memt = rman_get_bustag(bktr->res_mem); 357127808Snectar bktr->memh = rman_get_bushandle(bktr->res_mem); 358178825Sdfr 359127808Snectar 360127808Snectar /* 361142403Snectar * Disable the brooktree device 362127808Snectar */ 363178825Sdfr OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 364127808Snectar OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 365127808Snectar 366178825Sdfr 367127808Snectar#ifdef BROOKTREE_IRQ /* from the configuration file */ 368127808Snectar old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 369178825Sdfr pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 370233294Sstas new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 371127808Snectar printf("bktr%d: attach: irq changed from %d to %d\n", 372127808Snectar unit, (old_irq & 0xff), (new_irq & 0xff)); 373233294Sstas#endif 374178825Sdfr 375178825Sdfr /* 376233294Sstas * Allocate our interrupt. 377233294Sstas */ 378233294Sstas bktr->irq_rid = 0; 379102644Snectar bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 38090926Snectar 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 38172445Sassar if (bktr->res_irq == NULL) { 38255682Smarkm device_printf(dev, "could not map interrupt\n"); 383233294Sstas error = ENXIO; 38455682Smarkm goto fail; 38555682Smarkm } 38655682Smarkm 38755682Smarkm error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 38855682Smarkm bktr_intr, bktr, &bktr->res_ih); 38955682Smarkm if (error) { 390233294Sstas device_printf(dev, "could not setup irq\n"); 39155682Smarkm goto fail; 392120945Snectar 39390926Snectar } 39472445Sassar 39555682Smarkm 39690926Snectar /* Update the Device Control Register */ 397233294Sstas /* on Bt878 and Bt879 cards */ 39890926Snectar fun = pci_read_config( dev, 0x40, 2); 39955682Smarkm fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 400178825Sdfr 40190926Snectar#if defined( BKTR_430_FX_MODE ) 40290926Snectar if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 40390926Snectar fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 404233294Sstas#endif 40590926Snectar 40690926Snectar#if defined( BKTR_SIS_VIA_MODE ) 407178825Sdfr if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 40890926Snectar fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 40990926Snectar OPTi chipset motherboards too */ 41090926Snectar#endif 41190926Snectar pci_write_config(dev, 0x40, fun, 2); 41255682Smarkm 413178825Sdfr#if defined(BKTR_USE_FREEBSD_SMBUS) 414178825Sdfr if (bt848_i2c_attach(dev)) 415178825Sdfr printf("bktr%d: i2c_attach: can't attach\n", unit); 416178825Sdfr#endif 41772445Sassar 41872445Sassar/* 41972445Sassar * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 420178825Sdfr * you have more than four, then 16 would probably be a better value. 42172445Sassar */ 42272445Sassar#ifndef BROOKTREE_DEF_LATENCY_VALUE 42372445Sassar#define BROOKTREE_DEF_LATENCY_VALUE 10 42472445Sassar#endif 42555682Smarkm latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 426233294Sstas latency = (latency >> 8) & 0xff; 42790926Snectar if ( bootverbose ) { 42855682Smarkm if (latency) 42955682Smarkm printf("brooktree%d: PCI bus latency is", unit); 430233294Sstas else 431142403Snectar printf("brooktree%d: PCI bus latency was 0 changing to", 432142403Snectar unit); 433142403Snectar } 434142403Snectar if ( !latency ) { 435233294Sstas latency = BROOKTREE_DEF_LATENCY_VALUE; 436233294Sstas pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 437142403Snectar } 438142403Snectar if ( bootverbose ) { 439142403Snectar printf(" %d.\n", (int) latency); 440233294Sstas } 441233294Sstas 442233294Sstas /* read the pci device id and revision id */ 443142403Snectar fun = pci_get_devid(dev); 444142403Snectar rev = pci_get_revid(dev); 445142403Snectar 446142403Snectar /* call the common attach code */ 447142403Snectar common_bktr_attach( bktr, unit, fun, rev ); 448142403Snectar 449142403Snectar /* make the device entries */ 450142403Snectar bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 451142403Snectar 0, 0, 0444, "bktr%d", unit); 452142403Snectar bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 453142403Snectar 0, 0, 0444, "tuner%d", unit); 454142403Snectar bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 455142403Snectar 0, 0, 0444, "vbi%d" , unit); 456142403Snectar 457142403Snectar 458142403Snectar /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 459142403Snectar /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 460233294Sstas#if (__FreeBSD_version >=500000) 46155682Smarkm if (unit == 0) { 46255682Smarkm bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 463178825Sdfr bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 464233294Sstas bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 465233294Sstas } 466233294Sstas#endif 467233294Sstas 468233294Sstas return 0; 469233294Sstas 470233294Sstasfail: 471233294Sstas if (bktr->res_irq) 472233294Sstas bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 473233294Sstas if (bktr->res_mem) 474233294Sstas bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 475233294Sstas return error; 476233294Sstas 477233294Sstas} 478233294Sstas 479233294Sstas/* 480233294Sstas * the detach routine. 481233294Sstas */ 482233294Sstasstatic int 483233294Sstasbktr_detach( device_t dev ) 484233294Sstas{ 48555682Smarkm struct bktr_softc *bktr = device_get_softc(dev); 48655682Smarkm 48755682Smarkm#ifdef BKTR_NEW_MSP34XX_DRIVER 488233294Sstas /* Disable the soundchip and kernel thread */ 489233294Sstas if (bktr->msp3400c_info != NULL) 490233294Sstas msp_detach(bktr); 491233294Sstas#endif 492233294Sstas 493233294Sstas /* Disable the brooktree device */ 494233294Sstas OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 49555682Smarkm OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49690926Snectar 497233294Sstas#if defined(BKTR_USE_FREEBSD_SMBUS) 498233294Sstas if (bt848_i2c_detach(dev)) 499233294Sstas printf("bktr%d: i2c_attach: can't attach\n", 500233294Sstas device_get_unit(dev)); 501233294Sstas#endif 502233294Sstas 503233294Sstas /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50490926Snectar /* The memory is retained by the bktr_mem module so we can unload and */ 50590926Snectar /* then reload the main bktr driver module */ 506178825Sdfr 50790926Snectar /* Unregister the /dev/bktrN, tunerN and vbiN devices, 50855682Smarkm * the aliases for unit 0 are automatically destroyed */ 509142403Snectar destroy_dev(bktr->vbidev); 51055682Smarkm destroy_dev(bktr->tunerdev); 51155682Smarkm destroy_dev(bktr->bktrdev); 51255682Smarkm 51355682Smarkm /* 514233294Sstas * Deallocate resources. 515233294Sstas */ 516233294Sstas bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 517233294Sstas bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 518233294Sstas bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 519233294Sstas 520233294Sstas return 0; 521233294Sstas} 522233294Sstas 523233294Sstas/* 524233294Sstas * the shutdown routine. 525233294Sstas */ 52690926Snectarstatic int 527233294Sstasbktr_shutdown( device_t dev ) 528233294Sstas{ 529233294Sstas struct bktr_softc *bktr = device_get_softc(dev); 530233294Sstas 531233294Sstas /* Disable the brooktree device */ 53255682Smarkm OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53372445Sassar OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 534233294Sstas 535233294Sstas return 0; 536233294Sstas} 537233294Sstas 538233294Sstas 53990926Snectar/* 54072445Sassar * Special Memory Allocation 541233294Sstas */ 542233294Sstasvm_offset_t 543233294Sstasget_bktr_mem( int unit, unsigned size ) 544233294Sstas{ 545233294Sstas vm_offset_t addr = 0; 546102644Snectar 547102644Snectar addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 548102644Snectar if (addr == 0) 549102644Snectar addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 550102644Snectar if (addr == 0) { 551102644Snectar printf("bktr%d: Unable to allocate %d bytes of memory.\n", 552233294Sstas unit, size); 55390926Snectar } 554178825Sdfr 555233294Sstas return( addr ); 556233294Sstas} 557233294Sstas 558233294Sstas 559233294Sstas/*--------------------------------------------------------- 560233294Sstas** 561233294Sstas** BrookTree 848 character device driver routines 562233294Sstas** 563233294Sstas**--------------------------------------------------------- 564233294Sstas*/ 565233294Sstas 566233294Sstas#define VIDEO_DEV 0x00 567233294Sstas#define TUNER_DEV 0x01 568233294Sstas#define VBI_DEV 0x02 569233294Sstas 570233294Sstas#define UNIT(x) ((x) & 0x0f) 57155682Smarkm#define FUNCTION(x) (x >> 4) 572233294Sstas 573233294Sstas/* 574233294Sstas * 575233294Sstas */ 576233294Sstasstatic int 577233294Sstasbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 578233294Sstas{ 57955682Smarkm bktr_ptr_t bktr; 58090926Snectar int unit; 581233294Sstas int result; 582233294Sstas 583233294Sstas unit = UNIT( minor(dev) ); 584233294Sstas 585233294Sstas /* Get the device data */ 586233294Sstas bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 587233294Sstas if (bktr == NULL) { 588233294Sstas /* the device is no longer valid/functioning */ 589233294Sstas return (ENXIO); 59055682Smarkm } 59172445Sassar 592102644Snectar if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 59372445Sassar return( ENXIO ); 59472445Sassar 59572445Sassar /* Record that the device is now busy */ 596233294Sstas device_busy(devclass_get_device(bktr_devclass, unit)); 597233294Sstas 598102644Snectar 599142403Snectar if (bt848_card != -1) { 60055682Smarkm if ((bt848_card >> 8 == unit ) && 60172445Sassar ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 60272445Sassar if ( bktr->bt848_card != (bt848_card & 0xff) ) { 603233294Sstas bktr->bt848_card = (bt848_card & 0xff); 60455682Smarkm probeCard(bktr, FALSE, unit); 605102644Snectar } 60672445Sassar } 60772445Sassar } 60872445Sassar 609233294Sstas if (bt848_tuner != -1) { 610233294Sstas if ((bt848_tuner >> 8 == unit ) && 611233294Sstas ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 612233294Sstas if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 613178825Sdfr bktr->bt848_tuner = (bt848_tuner & 0xff); 614233294Sstas probeCard(bktr, FALSE, unit); 615233294Sstas } 616233294Sstas } 617233294Sstas } 618233294Sstas 619233294Sstas if (bt848_reverse_mute != -1) { 620233294Sstas if ((bt848_reverse_mute >> 8) == unit ) { 621178825Sdfr bktr->reverse_mute = bt848_reverse_mute & 0xff; 622127808Snectar } 623127808Snectar } 624127808Snectar 625127808Snectar if (bt848_slow_msp_audio != -1) { 626127808Snectar if ((bt848_slow_msp_audio >> 8) == unit ) { 627127808Snectar bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 628127808Snectar } 629233294Sstas } 630233294Sstas 631233294Sstas#ifdef BKTR_NEW_MSP34XX_DRIVER 632127808Snectar if (bt848_stereo_once != 0) { 633233294Sstas if ((bt848_stereo_once >> 8) == unit ) { 634127808Snectar bktr->stereo_once = (bt848_stereo_once & 0xff); 63578527Sassar } 636102644Snectar } 637233294Sstas 638233294Sstas if (bt848_amsound != -1) { 63978527Sassar if ((bt848_amsound >> 8) == unit ) { 64055682Smarkm bktr->amsound = (bt848_amsound & 0xff); 641127808Snectar } 64255682Smarkm } 64355682Smarkm 644233294Sstas if (bt848_dolby != -1) { 645233294Sstas if ((bt848_dolby >> 8) == unit ) { 646233294Sstas bktr->dolby = (bt848_dolby & 0xff); 647233294Sstas } 648233294Sstas } 649233294Sstas#endif 650233294Sstas 651233294Sstas switch ( FUNCTION( minor(dev) ) ) { 652233294Sstas case VIDEO_DEV: 653233294Sstas result = video_open( bktr ); 654233294Sstas break; 655233294Sstas case TUNER_DEV: 656233294Sstas result = tuner_open( bktr ); 657178825Sdfr break; 658178825Sdfr case VBI_DEV: 659178825Sdfr result = vbi_open( bktr ); 660178825Sdfr break; 661178825Sdfr default: 662178825Sdfr result = ENXIO; 663178825Sdfr break; 664178825Sdfr } 665178825Sdfr 666178825Sdfr /* If there was an error opening the device, undo the busy status */ 667178825Sdfr if (result != 0) 668178825Sdfr device_unbusy(devclass_get_device(bktr_devclass, unit)); 669102644Snectar return( result ); 67055682Smarkm} 671178825Sdfr 672233294Sstas 673233294Sstas/* 674233294Sstas * 675102644Snectar */ 676233294Sstasstatic int 677233294Sstasbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 678102644Snectar{ 679233294Sstas bktr_ptr_t bktr; 68055682Smarkm int unit; 681233294Sstas int result; 682233294Sstas 68372445Sassar unit = UNIT( minor(dev) ); 68455682Smarkm 68555682Smarkm /* Get the device data */ 68690926Snectar bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 687127808Snectar if (bktr == NULL) { 68890926Snectar /* the device is no longer valid/functioning */ 68955682Smarkm return (ENXIO); 69055682Smarkm } 69155682Smarkm 69290926Snectar switch ( FUNCTION( minor(dev) ) ) { 69390926Snectar case VIDEO_DEV: 694142403Snectar result = video_close( bktr ); 695178825Sdfr break; 696142403Snectar case TUNER_DEV: 69790926Snectar result = tuner_close( bktr ); 69855682Smarkm break; 69955682Smarkm case VBI_DEV: 70090926Snectar result = vbi_close( bktr ); 70155682Smarkm break; 70255682Smarkm default: 70355682Smarkm return (ENXIO); 70490926Snectar break; 70590926Snectar } 70655682Smarkm 70790926Snectar device_unbusy(devclass_get_device(bktr_devclass, unit)); 708127808Snectar return( result ); 70990926Snectar} 71090926Snectar 71155682Smarkm 71255682Smarkm/* 71355682Smarkm * 714178825Sdfr */ 71555682Smarkmstatic int 71655682Smarkmbktr_read( dev_t dev, struct uio *uio, int ioflag ) 717178825Sdfr{ 718233294Sstas bktr_ptr_t bktr; 71955682Smarkm int unit; 72055682Smarkm 72190926Snectar unit = UNIT(minor(dev)); 72290926Snectar 72390926Snectar /* Get the device data */ 72455682Smarkm bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 725142403Snectar if (bktr == NULL) { 726142403Snectar /* the device is no longer valid/functioning */ 72755682Smarkm return (ENXIO); 72890926Snectar } 729233294Sstas 730127808Snectar switch ( FUNCTION( minor(dev) ) ) { 73190926Snectar case VIDEO_DEV: 732178825Sdfr return( video_read( bktr, unit, dev, uio ) ); 73355682Smarkm case VBI_DEV: 73490926Snectar return( vbi_read( bktr, uio, ioflag ) ); 73555682Smarkm } 73690926Snectar return( ENXIO ); 73755682Smarkm} 738142403Snectar 739142403Snectar 740233294Sstas/* 741233294Sstas * 74290926Snectar */ 74355682Smarkmstatic int 74490926Snectarbktr_write( dev_t dev, struct uio *uio, int ioflag ) 74590926Snectar{ 746120945Snectar return( EINVAL ); /* XXX or ENXIO ? */ 747120945Snectar} 748120945Snectar 749178825Sdfr 750178825Sdfr/* 751233294Sstas * 752233294Sstas */ 75390926Snectarstatic int 75490926Snectarbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 75590926Snectar{ 756178825Sdfr bktr_ptr_t bktr; 757178825Sdfr int unit; 758233294Sstas 759233294Sstas unit = UNIT(minor(dev)); 76090926Snectar 76190926Snectar /* Get the device data */ 762233294Sstas bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 763233294Sstas if (bktr == NULL) { 76490926Snectar /* the device is no longer valid/functioning */ 76590926Snectar return (ENXIO); 766178825Sdfr } 767178825Sdfr 768233294Sstas if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 769233294Sstas return( ENOMEM ); 770178825Sdfr 771178825Sdfr switch ( FUNCTION( minor(dev) ) ) { 772233294Sstas case VIDEO_DEV: 773233294Sstas return( video_ioctl( bktr, unit, cmd, arg, td ) ); 77490926Snectar case TUNER_DEV: 77590926Snectar return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 77655682Smarkm } 777233294Sstas 778127808Snectar return( ENXIO ); 77990926Snectar} 78055682Smarkm 78190926Snectar 78255682Smarkm/* 78390926Snectar * 78490926Snectar */ 78590926Snectarstatic int 786127808Snectarbktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 787127808Snectar{ 788127808Snectar int unit; 789127808Snectar bktr_ptr_t bktr; 790127808Snectar 791127808Snectar unit = UNIT(minor(dev)); 792127808Snectar 793127808Snectar if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 794178825Sdfr return( -1 ); 795178825Sdfr 796178825Sdfr /* Get the device data */ 79790926Snectar bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 79890926Snectar if (bktr == NULL) { 799233294Sstas /* the device is no longer valid/functioning */ 800233294Sstas return (ENXIO); 801178825Sdfr } 802127808Snectar 803127808Snectar if (nprot & PROT_EXEC) 804178825Sdfr return( -1 ); 805142403Snectar 806142403Snectar if (offset < 0) 807178825Sdfr return( -1 ); 808178825Sdfr 809178825Sdfr if (offset >= bktr->alloc_pages * PAGE_SIZE) 810178825Sdfr return( -1 ); 811178825Sdfr 812178825Sdfr *paddr = vtophys(bktr->bigbuf) + offset; 813178825Sdfr return( 0 ); 814178825Sdfr} 815178825Sdfr 816178825Sdfrstatic int 81790926Snectarbktr_poll( dev_t dev, int events, struct thread *td) 81890926Snectar{ 81955682Smarkm int unit; 82055682Smarkm bktr_ptr_t bktr; 82155682Smarkm int revents = 0; 82255682Smarkm DECLARE_INTR_MASK(s); 82355682Smarkm 82472445Sassar unit = UNIT(minor(dev)); 82572445Sassar 82672445Sassar /* Get the device data */ 82772445Sassar bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 82855682Smarkm if (bktr == NULL) { 82955682Smarkm /* the device is no longer valid/functioning */ 83055682Smarkm return (ENXIO); 831178825Sdfr } 832178825Sdfr 83355682Smarkm DISABLE_INTR(s); 83455682Smarkm 83555682Smarkm if (events & (POLLIN | POLLRDNORM)) { 83655682Smarkm 83755682Smarkm switch ( FUNCTION( minor(dev) ) ) { 83855682Smarkm case VBI_DEV: 83972445Sassar if(bktr->vbisize == 0) 84072445Sassar selrecord(td, &bktr->vbi_select); 84155682Smarkm else 842178825Sdfr revents |= events & (POLLIN | POLLRDNORM); 843178825Sdfr break; 844178825Sdfr } 845178825Sdfr } 846178825Sdfr 847178825Sdfr ENABLE_INTR(s); 848178825Sdfr 849178825Sdfr return (revents); 850178825Sdfr} 851178825Sdfr 852178825Sdfr#endif /* FreeBSD 4.x specific kernel interface routines */ 85355682Smarkm 85455682Smarkm/*****************/ 85555682Smarkm/* *** BSDI *** */ 856102644Snectar/*****************/ 857102644Snectar 858178825Sdfr#if defined(__bsdi__) 859178825Sdfr#endif /* __bsdi__ BSDI specific kernel interface routines */ 860102644Snectar 861102644Snectar 862102644Snectar/*****************************/ 863102644Snectar/* *** OpenBSD / NetBSD *** */ 864102644Snectar/*****************************/ 865102644Snectar#if defined(__NetBSD__) || defined(__OpenBSD__) 866178825Sdfr 867102644Snectar#define IPL_VIDEO IPL_BIO /* XXX */ 868102644Snectar 869102644Snectarstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 870102644Snectar 871102644Snectar#define bktr_open bktropen 872102644Snectar#define bktr_close bktrclose 873102644Snectar#define bktr_read bktrread 874102644Snectar#define bktr_write bktrwrite 875102644Snectar#define bktr_ioctl bktrioctl 876102644Snectar#define bktr_mmap bktrmmap 877102644Snectar 878102644Snectarvm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 879102644Snectar vm_offset_t, vm_offset_t); 880102644Snectar 881102644Snectar#if defined(__OpenBSD__) 882178825Sdfrstatic int bktr_probe(struct device *, void *, void *); 883102644Snectar#else 884102644Snectarstatic int bktr_probe(struct device *, struct cfdata *, void *); 885102644Snectar#endif 886102644Snectarstatic void bktr_attach(struct device *, struct device *, void *); 887233294Sstas 888233294Sstasstruct cfattach bktr_ca = { 889233294Sstas sizeof(struct bktr_softc), bktr_probe, bktr_attach 89055682Smarkm}; 89155682Smarkm 89255682Smarkm#if defined(__NetBSD__) 89355682Smarkmextern struct cfdriver bktr_cd; 89455682Smarkm#else 89555682Smarkmstruct cfdriver bktr_cd = { 89655682Smarkm NULL, "bktr", DV_DULL 89755682Smarkm}; 89855682Smarkm#endif 89955682Smarkm 90055682Smarkmint 90155682Smarkmbktr_probe(parent, match, aux) 90255682Smarkm struct device *parent; 90355682Smarkm#if defined(__OpenBSD__) 90455682Smarkm void *match; 90555682Smarkm#else 90655682Smarkm struct cfdata *match; 90755682Smarkm#endif 90855682Smarkm void *aux; 90955682Smarkm{ 91055682Smarkm struct pci_attach_args *pa = aux; 91155682Smarkm 91255682Smarkm if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 91355682Smarkm (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 91455682Smarkm PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 91555682Smarkm PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 91655682Smarkm PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 91755682Smarkm return 1; 91855682Smarkm 91955682Smarkm return 0; 92055682Smarkm} 92155682Smarkm 92255682Smarkm 92355682Smarkm/* 92455682Smarkm * the attach routine. 92555682Smarkm */ 92655682Smarkmstatic void 92755682Smarkmbktr_attach(struct device *parent, struct device *self, void *aux) 92855682Smarkm{ 92955682Smarkm bktr_ptr_t bktr; 93055682Smarkm u_long latency; 93155682Smarkm u_long fun; 93255682Smarkm unsigned int rev; 93355682Smarkm 93455682Smarkm#if defined(__OpenBSD__) 93555682Smarkm struct pci_attach_args *pa = aux; 93655682Smarkm pci_chipset_tag_t pc = pa->pa_pc; 93755682Smarkm 93855682Smarkm pci_intr_handle_t ih; 93955682Smarkm const char *intrstr; 94055682Smarkm int retval; 94155682Smarkm int unit; 94255682Smarkm 94355682Smarkm bktr = (bktr_ptr_t)self; 94455682Smarkm unit = bktr->bktr_dev.dv_unit; 94555682Smarkm 94655682Smarkm bktr->pc = pa->pa_pc; 94755682Smarkm bktr->tag = pa->pa_tag; 94855682Smarkm bktr->dmat = pa->pa_dmat; 94955682Smarkm 95055682Smarkm /* 95155682Smarkm * map memory 95255682Smarkm */ 95355682Smarkm bktr->memt = pa->pa_memt; 95472445Sassar retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 955178825Sdfr &bktr->phys_base, &bktr->obmemsz, NULL); 95655682Smarkm if (!retval) 957178825Sdfr retval = bus_space_map(pa->pa_memt, bktr->phys_base, 958178825Sdfr bktr->obmemsz, 0, &bktr->memh); 959178825Sdfr if (retval) { 960120945Snectar printf(": couldn't map memory\n"); 961178825Sdfr return; 96255682Smarkm } 96355682Smarkm 96455682Smarkm 96555682Smarkm /* 96655682Smarkm * map interrupt 967178825Sdfr */ 968178825Sdfr if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 969178825Sdfr pa->pa_intrline, &ih)) { 970178825Sdfr printf(": couldn't map interrupt\n"); 971178825Sdfr return; 972178825Sdfr } 973178825Sdfr intrstr = pci_intr_string(pa->pa_pc, ih); 974178825Sdfr 975233294Sstas bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 976178825Sdfr bktr_intr, bktr, bktr->bktr_dev.dv_xname); 977178825Sdfr if (bktr->ih == NULL) { 978178825Sdfr printf(": couldn't establish interrupt"); 979178825Sdfr if (intrstr != NULL) 980178825Sdfr printf(" at %s", intrstr); 981178825Sdfr printf("\n"); 982178825Sdfr return; 983178825Sdfr } 984178825Sdfr 985178825Sdfr if (intrstr != NULL) 986178825Sdfr printf(": %s\n", intrstr); 987178825Sdfr#endif /* __OpenBSD__ */ 988178825Sdfr 989178825Sdfr#if defined(__NetBSD__) 990178825Sdfr struct pci_attach_args *pa = aux; 991178825Sdfr pci_intr_handle_t ih; 992178825Sdfr const char *intrstr; 993233294Sstas int retval; 99455682Smarkm int unit; 99555682Smarkm 99655682Smarkm bktr = (bktr_ptr_t)self; 997 unit = bktr->bktr_dev.dv_unit; 998 bktr->dmat = pa->pa_dmat; 999 1000 printf("\n"); 1001 1002 /* 1003 * map memory 1004 */ 1005 retval = pci_mapreg_map(pa, PCI_MAPREG_START, 1006 PCI_MAPREG_TYPE_MEM 1007 | PCI_MAPREG_MEM_TYPE_32BIT, 0, 1008 &bktr->memt, &bktr->memh, NULL, 1009 &bktr->obmemsz); 1010 DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 1011 bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 1012 if (retval) { 1013 printf("%s: couldn't map memory\n", bktr_name(bktr)); 1014 return; 1015 } 1016 1017 /* 1018 * Disable the brooktree device 1019 */ 1020 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 1021 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 1022 1023 /* 1024 * map interrupt 1025 */ 1026 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 1027 pa->pa_intrline, &ih)) { 1028 printf("%s: couldn't map interrupt\n", 1029 bktr_name(bktr)); 1030 return; 1031 } 1032 intrstr = pci_intr_string(pa->pa_pc, ih); 1033 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 1034 bktr_intr, bktr); 1035 if (bktr->ih == NULL) { 1036 printf("%s: couldn't establish interrupt", 1037 bktr_name(bktr)); 1038 if (intrstr != NULL) 1039 printf(" at %s", intrstr); 1040 printf("\n"); 1041 return; 1042 } 1043 if (intrstr != NULL) 1044 printf("%s: interrupting at %s\n", bktr_name(bktr), 1045 intrstr); 1046#endif /* __NetBSD__ */ 1047 1048/* 1049 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 1050 * you have more than four, then 16 would probably be a better value. 1051 */ 1052#ifndef BROOKTREE_DEF_LATENCY_VALUE 1053#define BROOKTREE_DEF_LATENCY_VALUE 10 1054#endif 1055 latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 1056 latency = (latency >> 8) & 0xff; 1057 1058 if (!latency) { 1059 if (bootverbose) { 1060 printf("%s: PCI bus latency was 0 changing to %d", 1061 bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 1062 } 1063 latency = BROOKTREE_DEF_LATENCY_VALUE; 1064 pci_conf_write(pa->pa_pc, pa->pa_tag, 1065 PCI_LATENCY_TIMER, latency<<8); 1066 } 1067 1068 1069 /* Enabled Bus Master 1070 XXX: check if all old DMA is stopped first (e.g. after warm 1071 boot) */ 1072 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1073 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 1074 fun | PCI_COMMAND_MASTER_ENABLE); 1075 1076 /* read the pci id and determine the card type */ 1077 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 1078 rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 1079 1080 common_bktr_attach(bktr, unit, fun, rev); 1081} 1082 1083 1084/* 1085 * Special Memory Allocation 1086 */ 1087vm_offset_t 1088get_bktr_mem(bktr, dmapp, size) 1089 bktr_ptr_t bktr; 1090 bus_dmamap_t *dmapp; 1091 unsigned int size; 1092{ 1093 bus_dma_tag_t dmat = bktr->dmat; 1094 bus_dma_segment_t seg; 1095 bus_size_t align; 1096 int rseg; 1097 caddr_t kva; 1098 1099 /* 1100 * Allocate a DMA area 1101 */ 1102 align = 1 << 24; 1103 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1104 &rseg, BUS_DMA_NOWAIT)) { 1105 align = PAGE_SIZE; 1106 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1107 &rseg, BUS_DMA_NOWAIT)) { 1108 printf("%s: Unable to dmamem_alloc of %d bytes\n", 1109 bktr_name(bktr), size); 1110 return 0; 1111 } 1112 } 1113 if (bus_dmamem_map(dmat, &seg, rseg, size, 1114 &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 1115 printf("%s: Unable to dmamem_map of %d bytes\n", 1116 bktr_name(bktr), size); 1117 bus_dmamem_free(dmat, &seg, rseg); 1118 return 0; 1119 } 1120#ifdef __OpenBSD__ 1121 bktr->dm_mapsize = size; 1122#endif 1123 /* 1124 * Create and locd the DMA map for the DMA area 1125 */ 1126 if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 1127 printf("%s: Unable to dmamap_create of %d bytes\n", 1128 bktr_name(bktr), size); 1129 bus_dmamem_unmap(dmat, kva, size); 1130 bus_dmamem_free(dmat, &seg, rseg); 1131 return 0; 1132 } 1133 if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 1134 printf("%s: Unable to dmamap_load of %d bytes\n", 1135 bktr_name(bktr), size); 1136 bus_dmamem_unmap(dmat, kva, size); 1137 bus_dmamem_free(dmat, &seg, rseg); 1138 bus_dmamap_destroy(dmat, *dmapp); 1139 return 0; 1140 } 1141 return (vm_offset_t)kva; 1142} 1143 1144void 1145free_bktr_mem(bktr, dmap, kva) 1146 bktr_ptr_t bktr; 1147 bus_dmamap_t dmap; 1148 vm_offset_t kva; 1149{ 1150 bus_dma_tag_t dmat = bktr->dmat; 1151 1152#ifdef __NetBSD__ 1153 bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 1154#else 1155 bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 1156#endif 1157 bus_dmamem_free(dmat, dmap->dm_segs, 1); 1158 bus_dmamap_destroy(dmat, dmap); 1159} 1160 1161 1162/*--------------------------------------------------------- 1163** 1164** BrookTree 848 character device driver routines 1165** 1166**--------------------------------------------------------- 1167*/ 1168 1169 1170#define VIDEO_DEV 0x00 1171#define TUNER_DEV 0x01 1172#define VBI_DEV 0x02 1173 1174#define UNIT(x) (minor((x) & 0x0f)) 1175#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 1176 1177/* 1178 * 1179 */ 1180int 1181bktr_open(dev_t dev, int flags, int fmt, struct thread *td) 1182{ 1183 bktr_ptr_t bktr; 1184 int unit; 1185 1186 unit = UNIT(dev); 1187 1188 /* unit out of range */ 1189 if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 1190 return(ENXIO); 1191 1192 bktr = bktr_cd.cd_devs[unit]; 1193 1194 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 1195 return(ENXIO); 1196 1197 switch (FUNCTION(dev)) { 1198 case VIDEO_DEV: 1199 return(video_open(bktr)); 1200 case TUNER_DEV: 1201 return(tuner_open(bktr)); 1202 case VBI_DEV: 1203 return(vbi_open(bktr)); 1204 } 1205 1206 return(ENXIO); 1207} 1208 1209 1210/* 1211 * 1212 */ 1213int 1214bktr_close(dev_t dev, int flags, int fmt, struct thread *td) 1215{ 1216 bktr_ptr_t bktr; 1217 int unit; 1218 1219 unit = UNIT(dev); 1220 1221 bktr = bktr_cd.cd_devs[unit]; 1222 1223 switch (FUNCTION(dev)) { 1224 case VIDEO_DEV: 1225 return(video_close(bktr)); 1226 case TUNER_DEV: 1227 return(tuner_close(bktr)); 1228 case VBI_DEV: 1229 return(vbi_close(bktr)); 1230 } 1231 1232 return(ENXIO); 1233} 1234 1235/* 1236 * 1237 */ 1238int 1239bktr_read(dev_t dev, struct uio *uio, int ioflag) 1240{ 1241 bktr_ptr_t bktr; 1242 int unit; 1243 1244 unit = UNIT(dev); 1245 1246 bktr = bktr_cd.cd_devs[unit]; 1247 1248 switch (FUNCTION(dev)) { 1249 case VIDEO_DEV: 1250 return(video_read(bktr, unit, dev, uio)); 1251 case VBI_DEV: 1252 return(vbi_read(bktr, uio, ioflag)); 1253 } 1254 1255 return(ENXIO); 1256} 1257 1258 1259/* 1260 * 1261 */ 1262int 1263bktr_write(dev_t dev, struct uio *uio, int ioflag) 1264{ 1265 /* operation not supported */ 1266 return(EOPNOTSUPP); 1267} 1268 1269/* 1270 * 1271 */ 1272int 1273bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 1274{ 1275 bktr_ptr_t bktr; 1276 int unit; 1277 1278 unit = UNIT(dev); 1279 1280 bktr = bktr_cd.cd_devs[unit]; 1281 1282 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 1283 return(ENOMEM); 1284 1285 switch (FUNCTION(dev)) { 1286 case VIDEO_DEV: 1287 return(video_ioctl(bktr, unit, cmd, arg, pr)); 1288 case TUNER_DEV: 1289 return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 1290 } 1291 1292 return(ENXIO); 1293} 1294 1295/* 1296 * 1297 */ 1298paddr_t 1299bktr_mmap(dev_t dev, off_t offset, int nprot) 1300{ 1301 int unit; 1302 bktr_ptr_t bktr; 1303 1304 unit = UNIT(dev); 1305 1306 if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 1307 return(-1); 1308 1309 bktr = bktr_cd.cd_devs[unit]; 1310 1311 if ((vaddr_t)offset < 0) 1312 return(-1); 1313 1314 if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 1315 return(-1); 1316 1317#ifdef __NetBSD__ 1318 return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 1319 (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 1320#else 1321 return(i386_btop(vtophys(bktr->bigbuf) + offset)); 1322#endif 1323} 1324 1325#endif /* __NetBSD__ || __OpenBSD__ */ 1326