bktr_os.c revision 119690
1119418Sobrien/*- 251694Sroger * 1. Redistributions of source code must retain the 351694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 451694Sroger * All rights reserved. 551694Sroger * 651694Sroger * Redistribution and use in source and binary forms, with or without 751694Sroger * modification, are permitted provided that the following conditions 851694Sroger * are met: 951694Sroger * 1. Redistributions of source code must retain the above copyright 1051694Sroger * notice, this list of conditions and the following disclaimer. 1151694Sroger * 2. Redistributions in binary form must reproduce the above copyright 1251694Sroger * notice, this list of conditions and the following disclaimer in the 1351694Sroger * documentation and/or other materials provided with the distribution. 1451694Sroger * 3. All advertising materials mentioning features or use of this software 1551694Sroger * must display the following acknowledgement: 1651694Sroger * This product includes software developed by Amancio Hasty and 1751694Sroger * Roger Hardiman 1851694Sroger * 4. The name of the author may not be used to endorse or promote products 1951694Sroger * derived from this software without specific prior written permission. 2051694Sroger * 2151694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2251694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2351694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2451694Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2551694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2651694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2751694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2851694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2951694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3051694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3151694Sroger * POSSIBILITY OF SUCH DAMAGE. 3251694Sroger */ 3351694Sroger 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_os.c 119690 2003-09-02 17:30:40Z jhb $"); 3651694Sroger 37119418Sobrien/* 38119418Sobrien * This is part of the Driver for Video Capture Cards (Frame grabbers) 39119418Sobrien * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 40119418Sobrien * chipset. 41119418Sobrien * Copyright Roger Hardiman and Amancio Hasty. 42119418Sobrien * 43119418Sobrien * bktr_os : This has all the Operating System dependant code, 44119418Sobrien * probe/attach and open/close/ioctl/read/mmap 45119418Sobrien * memory allocation 46119418Sobrien * PCI bus interfacing 47119418Sobrien */ 48119418Sobrien 4959014Sroger#include "opt_bktr.h" /* include any kernel config options */ 5051694Sroger 5151694Sroger#define FIFO_RISC_DISABLED 0 5251694Sroger#define ALL_INTS_DISABLED 0 5351694Sroger 5462214Sroger 5562214Sroger/*******************/ 5662214Sroger/* *** FreeBSD *** */ 5762214Sroger/*******************/ 5862214Sroger#ifdef __FreeBSD__ 5962214Sroger 6051694Sroger#include <sys/param.h> 6151694Sroger#include <sys/systm.h> 6251694Sroger#include <sys/conf.h> 6351694Sroger#include <sys/uio.h> 6451694Sroger#include <sys/kernel.h> 6551694Sroger#include <sys/signalvar.h> 6651694Sroger#include <sys/mman.h> 6751694Sroger#include <sys/poll.h> 6870834Swollman#if __FreeBSD_version >= 500014 6970834Swollman#include <sys/selinfo.h> 7070834Swollman#else 7151694Sroger#include <sys/select.h> 7270834Swollman#endif 7351694Sroger#include <sys/vnode.h> 7451694Sroger 7551694Sroger#include <vm/vm.h> 7651694Sroger#include <vm/vm_kern.h> 7751694Sroger#include <vm/pmap.h> 7851694Sroger#include <vm/vm_extern.h> 7951694Sroger 8093023Snsouch#if (__FreeBSD_version >=400000) 8151694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 8251694Sroger#endif 8351694Sroger 8459014Sroger#if (__FreeBSD_version >=300000) 8559014Sroger#include <machine/bus_memio.h> /* used by bus space */ 8659014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 8759014Sroger#include <sys/bus.h> 8859014Sroger#endif 8959014Sroger 9051694Sroger#if (__FreeBSD_version >=400000) 9151694Sroger#include <sys/rman.h> /* used by newbus */ 9251694Sroger#include <machine/resource.h> /* used by newbus */ 9351694Sroger#endif 9451694Sroger 9567306Sroger#if (__FreeBSD_version < 500000) 9667306Sroger#include <machine/clock.h> /* for DELAY */ 9751694Sroger#include <pci/pcivar.h> 9851694Sroger#include <pci/pcireg.h> 99119277Simp#else 100119277Simp#include <dev/pci/pcivar.h> 101119277Simp#include <dev/pci/pcireg.h> 102119277Simp#endif 10351694Sroger 10451694Sroger#include <sys/sysctl.h> 10551694Srogerint bt848_card = -1; 10651694Srogerint bt848_tuner = -1; 10751694Srogerint bt848_reverse_mute = -1; 10851694Srogerint bt848_format = -1; 10959014Srogerint bt848_slow_msp_audio = -1; 110118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 111118819Salexint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 112118819Salexint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 113118819Salex the autoscan seems work well only with FM... */ 114118819Salexint bt848_dolby = 0; 115118819Salex#endif 11651694Sroger 11751694SrogerSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 11851694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 11951694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 12051694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 12151694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 12259014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 123118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 124118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 125118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 126118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 127118819Salex#endif 12851694Sroger 12962214Sroger#endif /* end freebsd section */ 13051694Sroger 13162214Sroger 13262214Sroger 13351694Sroger/****************/ 13451694Sroger/* *** BSDI *** */ 13551694Sroger/****************/ 13651694Sroger#ifdef __bsdi__ 13751694Sroger#endif /* __bsdi__ */ 13851694Sroger 13951694Sroger 14051694Sroger/**************************/ 14151694Sroger/* *** OpenBSD/NetBSD *** */ 14251694Sroger/**************************/ 14351694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 14462214Sroger 14562214Sroger#include <sys/param.h> 14662214Sroger#include <sys/systm.h> 14762214Sroger#include <sys/conf.h> 14862214Sroger#include <sys/uio.h> 14962214Sroger#include <sys/kernel.h> 15062214Sroger#include <sys/signalvar.h> 15162214Sroger#include <sys/mman.h> 15262214Sroger#include <sys/poll.h> 15362214Sroger#include <sys/select.h> 15462214Sroger#include <sys/vnode.h> 15562214Sroger 15662214Sroger#include <vm/vm.h> 15762214Sroger 15862214Sroger#ifndef __NetBSD__ 15962214Sroger#include <vm/vm_kern.h> 16062214Sroger#include <vm/pmap.h> 16162214Sroger#include <vm/vm_extern.h> 16262214Sroger#endif 16362214Sroger 16459014Sroger#include <sys/device.h> 16559014Sroger#include <dev/pci/pcivar.h> 16659014Sroger#include <dev/pci/pcireg.h> 16759014Sroger#include <dev/pci/pcidevs.h> 16859014Sroger 16959014Sroger#define BKTR_DEBUG 17059014Sroger#ifdef BKTR_DEBUG 17159014Srogerint bktr_debug = 0; 17259014Sroger#define DPR(x) (bktr_debug ? printf x : 0) 17359014Sroger#else 17459014Sroger#define DPR(x) 17559014Sroger#endif 17651694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 17751694Sroger 17851694Sroger 17962214Sroger#ifdef __NetBSD__ 18062214Sroger#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 18162214Sroger#include <dev/pci/bktr/bktr_reg.h> 18262214Sroger#include <dev/pci/bktr/bktr_tuner.h> 18362214Sroger#include <dev/pci/bktr/bktr_card.h> 18462214Sroger#include <dev/pci/bktr/bktr_audio.h> 18562214Sroger#include <dev/pci/bktr/bktr_core.h> 18662214Sroger#include <dev/pci/bktr/bktr_os.h> 18762214Sroger#else /* Traditional location for .h files */ 18862214Sroger#include <machine/ioctl_meteor.h> 18962214Sroger#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 19062214Sroger#include <dev/bktr/bktr_reg.h> 19162214Sroger#include <dev/bktr/bktr_tuner.h> 19262214Sroger#include <dev/bktr/bktr_card.h> 19362214Sroger#include <dev/bktr/bktr_audio.h> 19462214Sroger#include <dev/bktr/bktr_core.h> 19562214Sroger#include <dev/bktr/bktr_os.h> 19693023Snsouch 19765692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 19865392Speter#include <dev/bktr/bktr_i2c.h> 19993023Snsouch 20093023Snsouch#include "iicbb_if.h" 20193023Snsouch#include "smbus_if.h" 20262214Sroger#endif 20365392Speter#endif 20451694Sroger 20562214Sroger 20651694Sroger/****************************/ 20751694Sroger/* *** FreeBSD 4.x code *** */ 20851694Sroger/****************************/ 20951694Sroger#if (__FreeBSD_version >= 400000) 21051694Sroger 21151694Srogerstatic int bktr_probe( device_t dev ); 21251694Srogerstatic int bktr_attach( device_t dev ); 21351694Srogerstatic int bktr_detach( device_t dev ); 21451694Srogerstatic int bktr_shutdown( device_t dev ); 21551694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21651694Sroger 21751694Srogerstatic device_method_t bktr_methods[] = { 21851694Sroger /* Device interface */ 21951694Sroger DEVMETHOD(device_probe, bktr_probe), 22051694Sroger DEVMETHOD(device_attach, bktr_attach), 22151694Sroger DEVMETHOD(device_detach, bktr_detach), 22251694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 22351694Sroger 22493023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 22593023Snsouch /* iicbb interface */ 22693023Snsouch DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22793023Snsouch DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 22893023Snsouch DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 22993023Snsouch DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 23093023Snsouch DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 23193023Snsouch DEVMETHOD(iicbb_reset, bti2c_iic_reset), 23293023Snsouch 23393023Snsouch /* smbus interface */ 23493023Snsouch DEVMETHOD(smbus_callback, bti2c_smb_callback), 23593023Snsouch DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 23693023Snsouch DEVMETHOD(smbus_writew, bti2c_smb_writew), 23793023Snsouch DEVMETHOD(smbus_readb, bti2c_smb_readb), 23893023Snsouch#endif 23993023Snsouch 24051694Sroger { 0, 0 } 24151694Sroger}; 24251694Sroger 24351694Srogerstatic driver_t bktr_driver = { 24451694Sroger "bktr", 24551694Sroger bktr_methods, 24651694Sroger sizeof(struct bktr_softc), 24751694Sroger}; 24851694Sroger 24951694Srogerstatic devclass_t bktr_devclass; 25051694Sroger 25151694Srogerstatic d_open_t bktr_open; 25251694Srogerstatic d_close_t bktr_close; 25351694Srogerstatic d_read_t bktr_read; 25451694Srogerstatic d_write_t bktr_write; 25551694Srogerstatic d_ioctl_t bktr_ioctl; 25651694Srogerstatic d_mmap_t bktr_mmap; 25751694Srogerstatic d_poll_t bktr_poll; 25851694Sroger 25951694Sroger#define CDEV_MAJOR 92 26051694Srogerstatic struct cdevsw bktr_cdevsw = { 261111815Sphk .d_open = bktr_open, 262111815Sphk .d_close = bktr_close, 263111815Sphk .d_read = bktr_read, 264111815Sphk .d_write = bktr_write, 265111815Sphk .d_ioctl = bktr_ioctl, 266111815Sphk .d_poll = bktr_poll, 267111815Sphk .d_mmap = bktr_mmap, 268111815Sphk .d_name = "bktr", 269111815Sphk .d_maj = CDEV_MAJOR, 27051694Sroger}; 27151694Sroger 27252995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 27367306Sroger#if (__FreeBSD_version > 410000) 27465728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27565728SrogerMODULE_VERSION(bktr, 1); 27667306Sroger#endif 27751694Sroger 27851694Sroger 27951694Sroger/* 28051694Sroger * the boot time probe routine. 28151694Sroger */ 28251694Srogerstatic int 28351694Srogerbktr_probe( device_t dev ) 28451694Sroger{ 28551694Sroger unsigned int type = pci_get_devid(dev); 28651694Sroger unsigned int rev = pci_get_revid(dev); 28751694Sroger 28867306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 28967306Sroger { 29067306Sroger switch (PCI_PRODUCT(type)) { 29167306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 29267306Sroger if (rev == 0x12) 29367306Sroger device_set_desc(dev, "BrookTree 848A"); 29467306Sroger else 29567306Sroger device_set_desc(dev, "BrookTree 848"); 29667306Sroger return 0; 29767306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 29867306Sroger device_set_desc(dev, "BrookTree 849A"); 29967306Sroger return 0; 30067306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 30167306Sroger device_set_desc(dev, "BrookTree 878"); 30267306Sroger return 0; 30367306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 30467306Sroger device_set_desc(dev, "BrookTree 879"); 30567306Sroger return 0; 30667306Sroger } 30751694Sroger }; 30851694Sroger 30951694Sroger return ENXIO; 31051694Sroger} 31151694Sroger 31251694Sroger 31351694Sroger/* 31451694Sroger * the attach routine. 31551694Sroger */ 31651694Srogerstatic int 31751694Srogerbktr_attach( device_t dev ) 31851694Sroger{ 31951694Sroger u_long latency; 32051694Sroger u_long fun; 32151694Sroger u_long val; 32251694Sroger unsigned int rev; 32351694Sroger unsigned int unit; 32451694Sroger int error = 0; 32551694Sroger#ifdef BROOKTREE_IRQ 32651694Sroger u_long old_irq, new_irq; 32751694Sroger#endif 32851694Sroger 32951694Sroger struct bktr_softc *bktr = device_get_softc(dev); 33051694Sroger 33151694Sroger unit = device_get_unit(dev); 33251694Sroger 33362112Sroger /* build the device name for bktr_name() */ 33462112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 33562112Sroger 33651694Sroger /* 33751694Sroger * Enable bus mastering and Memory Mapped device 33851694Sroger */ 33951694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 34051694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 34151694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 34251694Sroger 34351694Sroger /* 34451694Sroger * Map control/status registers. 34551694Sroger */ 346119690Sjhb bktr->mem_rid = PCIR_BAR(0); 34765049Sroger bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 34865049Sroger 0, ~0, 1, RF_ACTIVE); 34951694Sroger 35065049Sroger 35151694Sroger if (!bktr->res_mem) { 35251694Sroger device_printf(dev, "could not map memory\n"); 35351694Sroger error = ENXIO; 35451694Sroger goto fail; 35551694Sroger } 35659014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 35759014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 35851694Sroger 35959014Sroger 36051694Sroger /* 36151694Sroger * Disable the brooktree device 36251694Sroger */ 36359014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 36459014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 36551694Sroger 36651694Sroger 36751694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 36851694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36951694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 37051694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 37151694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 37251694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 37351694Sroger#endif 37451694Sroger 37551694Sroger /* 37651694Sroger * Allocate our interrupt. 37751694Sroger */ 37865049Sroger bktr->irq_rid = 0; 37965049Sroger bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 38065049Sroger 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 38151694Sroger if (bktr->res_irq == NULL) { 38251694Sroger device_printf(dev, "could not map interrupt\n"); 38351694Sroger error = ENXIO; 38451694Sroger goto fail; 38551694Sroger } 38651694Sroger 38759250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 38851694Sroger bktr_intr, bktr, &bktr->res_ih); 38951694Sroger if (error) { 39051694Sroger device_printf(dev, "could not setup irq\n"); 39151694Sroger goto fail; 39251694Sroger 39351694Sroger } 39451694Sroger 39551694Sroger 39651694Sroger /* Update the Device Control Register */ 39751694Sroger /* on Bt878 and Bt879 cards */ 39851694Sroger fun = pci_read_config( dev, 0x40, 2); 39951694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 40051694Sroger 40151694Sroger#if defined( BKTR_430_FX_MODE ) 40251694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 40351694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 40451694Sroger#endif 40551694Sroger 40651694Sroger#if defined( BKTR_SIS_VIA_MODE ) 40751694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 40851694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 40951694Sroger OPTi chipset motherboards too */ 41051694Sroger#endif 41151694Sroger pci_write_config(dev, 0x40, fun, 2); 41251694Sroger 41365692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 41493023Snsouch if (bt848_i2c_attach(dev)) 41551694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 41651694Sroger#endif 41751694Sroger 41851694Sroger/* 41951694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 42051694Sroger * you have more than four, then 16 would probably be a better value. 42151694Sroger */ 42251694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 42351694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 42451694Sroger#endif 42551694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 42651694Sroger latency = (latency >> 8) & 0xff; 42751694Sroger if ( bootverbose ) { 42851694Sroger if (latency) 42951694Sroger printf("brooktree%d: PCI bus latency is", unit); 43051694Sroger else 43151694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 43251694Sroger unit); 43351694Sroger } 43451694Sroger if ( !latency ) { 43551694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 43651694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 43751694Sroger } 43851694Sroger if ( bootverbose ) { 43951694Sroger printf(" %d.\n", (int) latency); 44051694Sroger } 44151694Sroger 44251694Sroger /* read the pci device id and revision id */ 44351694Sroger fun = pci_get_devid(dev); 44451694Sroger rev = pci_get_revid(dev); 44551694Sroger 44651694Sroger /* call the common attach code */ 44751694Sroger common_bktr_attach( bktr, unit, fun, rev ); 44851694Sroger 44967306Sroger /* make the device entries */ 45067306Sroger bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 45167306Sroger 0, 0, 0444, "bktr%d", unit); 45267306Sroger bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 45367306Sroger 0, 0, 0444, "tuner%d", unit); 45467306Sroger bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 45567306Sroger 0, 0, 0444, "vbi%d" , unit); 45651694Sroger 45767306Sroger 45867306Sroger /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 45967306Sroger /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 46067306Sroger#if (__FreeBSD_version >=500000) 46167306Sroger if (unit == 0) { 46267306Sroger bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 46367306Sroger bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 46467306Sroger bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 46567306Sroger } 46667306Sroger#endif 46767306Sroger 46851694Sroger return 0; 46951694Sroger 47051694Srogerfail: 47165049Sroger if (bktr->res_irq) 47265049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 47365049Sroger if (bktr->res_mem) 47465049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 47551694Sroger return error; 47651694Sroger 47751694Sroger} 47851694Sroger 47951694Sroger/* 48051694Sroger * the detach routine. 48151694Sroger */ 48251694Srogerstatic int 48351694Srogerbktr_detach( device_t dev ) 48451694Sroger{ 48551694Sroger struct bktr_softc *bktr = device_get_softc(dev); 48651694Sroger 487118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 488118819Salex /* Disable the soundchip and kernel thread */ 489118819Salex if (bktr->msp3400c_info != NULL) 490118819Salex msp_detach(bktr); 491118819Salex#endif 492118819Salex 49351694Sroger /* Disable the brooktree device */ 49459014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 49559014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49651694Sroger 49793023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 49893023Snsouch if (bt848_i2c_detach(dev)) 499115556Sphk printf("bktr%d: i2c_attach: can't attach\n", 500115556Sphk device_get_unit(dev)); 50193023Snsouch#endif 50293023Snsouch 50367306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50467306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 50567306Sroger /* then reload the main bktr driver module */ 50651694Sroger 507107699Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices, 508107699Sroger * the aliases for unit 0 are automatically destroyed */ 50967306Sroger destroy_dev(bktr->vbidev); 51067306Sroger destroy_dev(bktr->tunerdev); 51167306Sroger destroy_dev(bktr->bktrdev); 51267306Sroger 51351694Sroger /* 51451694Sroger * Deallocate resources. 51551694Sroger */ 51651694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 51765049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 51865049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 51965049Sroger 52051694Sroger return 0; 52151694Sroger} 52251694Sroger 52351694Sroger/* 52451694Sroger * the shutdown routine. 52551694Sroger */ 52651694Srogerstatic int 52751694Srogerbktr_shutdown( device_t dev ) 52851694Sroger{ 52951694Sroger struct bktr_softc *bktr = device_get_softc(dev); 53051694Sroger 53151694Sroger /* Disable the brooktree device */ 53259014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 53451694Sroger 53551694Sroger return 0; 53651694Sroger} 53751694Sroger 53851694Sroger 53951694Sroger/* 54051694Sroger * Special Memory Allocation 54151694Sroger */ 54251694Srogervm_offset_t 54351694Srogerget_bktr_mem( int unit, unsigned size ) 54451694Sroger{ 54551694Sroger vm_offset_t addr = 0; 54651694Sroger 54751694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 54851694Sroger if (addr == 0) 54951694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 55051694Sroger if (addr == 0) { 55151694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 55251694Sroger unit, size); 55351694Sroger } 55451694Sroger 55551694Sroger return( addr ); 55651694Sroger} 55751694Sroger 55851694Sroger 55951694Sroger/*--------------------------------------------------------- 56051694Sroger** 56151694Sroger** BrookTree 848 character device driver routines 56251694Sroger** 56351694Sroger**--------------------------------------------------------- 56451694Sroger*/ 56551694Sroger 56651694Sroger#define VIDEO_DEV 0x00 56751694Sroger#define TUNER_DEV 0x01 56851694Sroger#define VBI_DEV 0x02 56951694Sroger 57051694Sroger#define UNIT(x) ((x) & 0x0f) 57151694Sroger#define FUNCTION(x) (x >> 4) 57251694Sroger 57351694Sroger/* 57451694Sroger * 57551694Sroger */ 576104094Sphkstatic int 57783366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 57851694Sroger{ 57951694Sroger bktr_ptr_t bktr; 58051694Sroger int unit; 58151694Sroger int result; 58251694Sroger 58351694Sroger unit = UNIT( minor(dev) ); 58451694Sroger 58551694Sroger /* Get the device data */ 58651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 58751694Sroger if (bktr == NULL) { 58851694Sroger /* the device is no longer valid/functioning */ 58951694Sroger return (ENXIO); 59051694Sroger } 59151694Sroger 59251694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 59351694Sroger return( ENXIO ); 59451694Sroger 59551694Sroger /* Record that the device is now busy */ 59651694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 59751694Sroger 59851694Sroger 59951694Sroger if (bt848_card != -1) { 60051694Sroger if ((bt848_card >> 8 == unit ) && 60151694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 60251694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 60351694Sroger bktr->bt848_card = (bt848_card & 0xff); 60451694Sroger probeCard(bktr, FALSE, unit); 60551694Sroger } 60651694Sroger } 60751694Sroger } 60851694Sroger 60951694Sroger if (bt848_tuner != -1) { 61051694Sroger if ((bt848_tuner >> 8 == unit ) && 61151694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 61251694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 61351694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 61451694Sroger probeCard(bktr, FALSE, unit); 61551694Sroger } 61651694Sroger } 61751694Sroger } 61851694Sroger 61951694Sroger if (bt848_reverse_mute != -1) { 62059014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 62151694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 62251694Sroger } 62351694Sroger } 62451694Sroger 62559014Sroger if (bt848_slow_msp_audio != -1) { 62659014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 62759014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 62859014Sroger } 62959014Sroger } 63059014Sroger 631118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 632118819Salex if (bt848_stereo_once != 0) { 633118819Salex if ((bt848_stereo_once >> 8) == unit ) { 634118819Salex bktr->stereo_once = (bt848_stereo_once & 0xff); 635118819Salex } 636118819Salex } 637118819Salex 638118819Salex if (bt848_amsound != -1) { 639118819Salex if ((bt848_amsound >> 8) == unit ) { 640118819Salex bktr->amsound = (bt848_amsound & 0xff); 641118819Salex } 642118819Salex } 643118819Salex 644118819Salex if (bt848_dolby != -1) { 645118819Salex if ((bt848_dolby >> 8) == unit ) { 646118819Salex bktr->dolby = (bt848_dolby & 0xff); 647118819Salex } 648118819Salex } 649118819Salex#endif 650118819Salex 65151694Sroger switch ( FUNCTION( minor(dev) ) ) { 65251694Sroger case VIDEO_DEV: 65351694Sroger result = video_open( bktr ); 65451694Sroger break; 65551694Sroger case TUNER_DEV: 65651694Sroger result = tuner_open( bktr ); 65751694Sroger break; 65851694Sroger case VBI_DEV: 65951694Sroger result = vbi_open( bktr ); 66051694Sroger break; 66151694Sroger default: 66251694Sroger result = ENXIO; 66351694Sroger break; 66451694Sroger } 66551694Sroger 66651694Sroger /* If there was an error opening the device, undo the busy status */ 66751694Sroger if (result != 0) 66851694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 66951694Sroger return( result ); 67051694Sroger} 67151694Sroger 67251694Sroger 67351694Sroger/* 67451694Sroger * 67551694Sroger */ 676104094Sphkstatic int 67783366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 67851694Sroger{ 67951694Sroger bktr_ptr_t bktr; 68051694Sroger int unit; 68151694Sroger int result; 68251694Sroger 68351694Sroger unit = UNIT( minor(dev) ); 68451694Sroger 68551694Sroger /* Get the device data */ 68651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 68751694Sroger if (bktr == NULL) { 68851694Sroger /* the device is no longer valid/functioning */ 68951694Sroger return (ENXIO); 69051694Sroger } 69151694Sroger 69251694Sroger switch ( FUNCTION( minor(dev) ) ) { 69351694Sroger case VIDEO_DEV: 69451694Sroger result = video_close( bktr ); 69551694Sroger break; 69651694Sroger case TUNER_DEV: 69751694Sroger result = tuner_close( bktr ); 69851694Sroger break; 69951694Sroger case VBI_DEV: 70051694Sroger result = vbi_close( bktr ); 70151694Sroger break; 70251694Sroger default: 70351694Sroger return (ENXIO); 70451694Sroger break; 70551694Sroger } 70651694Sroger 70751694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 70851694Sroger return( result ); 70951694Sroger} 71051694Sroger 71151694Sroger 71251694Sroger/* 71351694Sroger * 71451694Sroger */ 715104094Sphkstatic int 71651694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 71751694Sroger{ 71851694Sroger bktr_ptr_t bktr; 71951694Sroger int unit; 72051694Sroger 72151694Sroger unit = UNIT(minor(dev)); 72251694Sroger 72351694Sroger /* Get the device data */ 72451694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 72551694Sroger if (bktr == NULL) { 72651694Sroger /* the device is no longer valid/functioning */ 72751694Sroger return (ENXIO); 72851694Sroger } 72951694Sroger 73051694Sroger switch ( FUNCTION( minor(dev) ) ) { 73151694Sroger case VIDEO_DEV: 73251694Sroger return( video_read( bktr, unit, dev, uio ) ); 73351694Sroger case VBI_DEV: 73451694Sroger return( vbi_read( bktr, uio, ioflag ) ); 73551694Sroger } 73651694Sroger return( ENXIO ); 73751694Sroger} 73851694Sroger 73951694Sroger 74051694Sroger/* 74151694Sroger * 74251694Sroger */ 743104094Sphkstatic int 74451694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 74551694Sroger{ 74651694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 74751694Sroger} 74851694Sroger 74951694Sroger 75051694Sroger/* 75151694Sroger * 75251694Sroger */ 753104094Sphkstatic int 75483366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 75551694Sroger{ 75651694Sroger bktr_ptr_t bktr; 75751694Sroger int unit; 75851694Sroger 75951694Sroger unit = UNIT(minor(dev)); 76051694Sroger 76151694Sroger /* Get the device data */ 76251694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76351694Sroger if (bktr == NULL) { 76451694Sroger /* the device is no longer valid/functioning */ 76551694Sroger return (ENXIO); 76651694Sroger } 76751694Sroger 76851694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 76951694Sroger return( ENOMEM ); 77051694Sroger 77151694Sroger switch ( FUNCTION( minor(dev) ) ) { 77251694Sroger case VIDEO_DEV: 77383366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 77451694Sroger case TUNER_DEV: 77583366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 77651694Sroger } 77751694Sroger 77851694Sroger return( ENXIO ); 77951694Sroger} 78051694Sroger 78151694Sroger 78251694Sroger/* 78351694Sroger * 78451694Sroger */ 785104094Sphkstatic int 786112569Sjakebktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 78751694Sroger{ 78851694Sroger int unit; 78951694Sroger bktr_ptr_t bktr; 79051694Sroger 79151694Sroger unit = UNIT(minor(dev)); 79251694Sroger 79351694Sroger if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 79451694Sroger return( -1 ); 79551694Sroger 79651694Sroger /* Get the device data */ 79751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 79851694Sroger if (bktr == NULL) { 79951694Sroger /* the device is no longer valid/functioning */ 80051694Sroger return (ENXIO); 80151694Sroger } 80251694Sroger 80351694Sroger if (nprot & PROT_EXEC) 80451694Sroger return( -1 ); 80551694Sroger 80651694Sroger if (offset < 0) 80751694Sroger return( -1 ); 80851694Sroger 80951694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 81051694Sroger return( -1 ); 81151694Sroger 812111462Smux *paddr = vtophys(bktr->bigbuf) + offset; 813111462Smux return( 0 ); 81451694Sroger} 81551694Sroger 816104094Sphkstatic int 817104094Sphkbktr_poll( dev_t dev, int events, struct thread *td) 81851694Sroger{ 81951694Sroger int unit; 82051694Sroger bktr_ptr_t bktr; 82151694Sroger int revents = 0; 82259277Sroger DECLARE_INTR_MASK(s); 82351694Sroger 82451694Sroger unit = UNIT(minor(dev)); 82551694Sroger 82651694Sroger /* Get the device data */ 82751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 82851694Sroger if (bktr == NULL) { 82951694Sroger /* the device is no longer valid/functioning */ 83051694Sroger return (ENXIO); 83151694Sroger } 83251694Sroger 83359277Sroger DISABLE_INTR(s); 83451694Sroger 83551694Sroger if (events & (POLLIN | POLLRDNORM)) { 83651694Sroger 83751694Sroger switch ( FUNCTION( minor(dev) ) ) { 83851694Sroger case VBI_DEV: 83951694Sroger if(bktr->vbisize == 0) 84083366Sjulian selrecord(td, &bktr->vbi_select); 84151694Sroger else 84251694Sroger revents |= events & (POLLIN | POLLRDNORM); 84351694Sroger break; 84451694Sroger } 84551694Sroger } 84651694Sroger 84759250Sroger ENABLE_INTR(s); 84851694Sroger 84951694Sroger return (revents); 85051694Sroger} 85151694Sroger 85251694Sroger#endif /* FreeBSD 4.x specific kernel interface routines */ 85351694Sroger 85451694Sroger/*****************/ 85551694Sroger/* *** BSDI *** */ 85651694Sroger/*****************/ 85751694Sroger 85851694Sroger#if defined(__bsdi__) 85951694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 86051694Sroger 86151694Sroger 86251694Sroger/*****************************/ 86351694Sroger/* *** OpenBSD / NetBSD *** */ 86451694Sroger/*****************************/ 86551694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 86659014Sroger 86759014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 86859014Sroger 86959014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 87059014Sroger 87159014Sroger#define bktr_open bktropen 87259014Sroger#define bktr_close bktrclose 87359014Sroger#define bktr_read bktrread 87459014Sroger#define bktr_write bktrwrite 87559014Sroger#define bktr_ioctl bktrioctl 87659014Sroger#define bktr_mmap bktrmmap 87759014Sroger 87859014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 87959014Sroger vm_offset_t, vm_offset_t); 88059014Sroger 88162112Sroger#if defined(__OpenBSD__) 88292739Salfredstatic int bktr_probe(struct device *, void *, void *); 88359014Sroger#else 88492739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 88559014Sroger#endif 88692739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 88759014Sroger 88859014Srogerstruct cfattach bktr_ca = { 88959014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 89059014Sroger}; 89159014Sroger 89259014Sroger#if defined(__NetBSD__) 89359014Srogerextern struct cfdriver bktr_cd; 89459014Sroger#else 89559014Srogerstruct cfdriver bktr_cd = { 89659014Sroger NULL, "bktr", DV_DULL 89759014Sroger}; 89859014Sroger#endif 89959014Sroger 90062112Srogerint 90162112Srogerbktr_probe(parent, match, aux) 90262112Sroger struct device *parent; 90362112Sroger#if defined(__OpenBSD__) 90459014Sroger void *match; 90559014Sroger#else 90659014Sroger struct cfdata *match; 90759014Sroger#endif 90859014Sroger void *aux; 90959014Sroger{ 91059014Sroger struct pci_attach_args *pa = aux; 91159014Sroger 91259014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 91359014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 91459014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 91559014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 91659014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 91759014Sroger return 1; 91859014Sroger 91959014Sroger return 0; 92059014Sroger} 92159014Sroger 92259014Sroger 92359014Sroger/* 92459014Sroger * the attach routine. 92559014Sroger */ 92659014Srogerstatic void 92762112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 92859014Sroger{ 92959014Sroger bktr_ptr_t bktr; 93059014Sroger u_long latency; 93159014Sroger u_long fun; 93259014Sroger unsigned int rev; 93359014Sroger 93459014Sroger#if defined(__OpenBSD__) 93559014Sroger struct pci_attach_args *pa = aux; 93659014Sroger pci_chipset_tag_t pc = pa->pa_pc; 93759014Sroger 93859014Sroger pci_intr_handle_t ih; 93959014Sroger const char *intrstr; 94059014Sroger int retval; 94159014Sroger int unit; 94259014Sroger 94359014Sroger bktr = (bktr_ptr_t)self; 94459014Sroger unit = bktr->bktr_dev.dv_unit; 94559014Sroger 94659014Sroger bktr->pc = pa->pa_pc; 94759014Sroger bktr->tag = pa->pa_tag; 94859014Sroger bktr->dmat = pa->pa_dmat; 94959014Sroger 95059014Sroger /* 95159014Sroger * map memory 95259014Sroger */ 95359014Sroger bktr->memt = pa->pa_memt; 95459014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 95559014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 95659014Sroger if (!retval) 95759014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 95859014Sroger bktr->obmemsz, 0, &bktr->memh); 95959014Sroger if (retval) { 96059014Sroger printf(": couldn't map memory\n"); 96159014Sroger return; 96259014Sroger } 96359014Sroger 96459014Sroger 96559014Sroger /* 96659014Sroger * map interrupt 96759014Sroger */ 96859014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 96959014Sroger pa->pa_intrline, &ih)) { 97059014Sroger printf(": couldn't map interrupt\n"); 97159014Sroger return; 97259014Sroger } 97359014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 97459014Sroger 97559014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 97659014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 97759014Sroger if (bktr->ih == NULL) { 97859014Sroger printf(": couldn't establish interrupt"); 97959014Sroger if (intrstr != NULL) 98059014Sroger printf(" at %s", intrstr); 98159014Sroger printf("\n"); 98259014Sroger return; 98359014Sroger } 98459014Sroger 98559014Sroger if (intrstr != NULL) 98659014Sroger printf(": %s\n", intrstr); 98759014Sroger#endif /* __OpenBSD__ */ 98859014Sroger 98959014Sroger#if defined(__NetBSD__) 99059014Sroger struct pci_attach_args *pa = aux; 99159014Sroger pci_intr_handle_t ih; 99259014Sroger const char *intrstr; 99359014Sroger int retval; 99459014Sroger int unit; 99559014Sroger 99659014Sroger bktr = (bktr_ptr_t)self; 99759014Sroger unit = bktr->bktr_dev.dv_unit; 99859014Sroger bktr->dmat = pa->pa_dmat; 99959014Sroger 100059014Sroger printf("\n"); 100159014Sroger 100259014Sroger /* 100359014Sroger * map memory 100459014Sroger */ 100559014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 100662112Sroger PCI_MAPREG_TYPE_MEM 100762112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 100862112Sroger &bktr->memt, &bktr->memh, NULL, 100962112Sroger &bktr->obmemsz); 101062112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 101162112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 101259014Sroger if (retval) { 101362112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 101459014Sroger return; 101559014Sroger } 101659014Sroger 101759014Sroger /* 101859014Sroger * Disable the brooktree device 101959014Sroger */ 102059014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 102159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 102259014Sroger 102359014Sroger /* 102459014Sroger * map interrupt 102559014Sroger */ 102659014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 102759014Sroger pa->pa_intrline, &ih)) { 102862112Sroger printf("%s: couldn't map interrupt\n", 102962112Sroger bktr_name(bktr)); 103059014Sroger return; 103159014Sroger } 103259014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 103359014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 103459014Sroger bktr_intr, bktr); 103559014Sroger if (bktr->ih == NULL) { 103659014Sroger printf("%s: couldn't establish interrupt", 103762112Sroger bktr_name(bktr)); 103862112Sroger if (intrstr != NULL) 103962112Sroger printf(" at %s", intrstr); 104062112Sroger printf("\n"); 104162112Sroger return; 104259014Sroger } 104359014Sroger if (intrstr != NULL) 104462112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 104559014Sroger intrstr); 104659014Sroger#endif /* __NetBSD__ */ 104759014Sroger 104859014Sroger/* 104959014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 105059014Sroger * you have more than four, then 16 would probably be a better value. 105159014Sroger */ 105259014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 105359014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 105459014Sroger#endif 105559014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 105659014Sroger latency = (latency >> 8) & 0xff; 105759014Sroger 105862112Sroger if (!latency) { 105962112Sroger if (bootverbose) { 106059014Sroger printf("%s: PCI bus latency was 0 changing to %d", 106162112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 106259014Sroger } 106359014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 106459014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 106559014Sroger PCI_LATENCY_TIMER, latency<<8); 106659014Sroger } 106759014Sroger 106859014Sroger 106962112Sroger /* Enabled Bus Master 107062112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 107162112Sroger boot) */ 107259014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 107362112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 107462112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 107559014Sroger 107659014Sroger /* read the pci id and determine the card type */ 107759014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 107859014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 107959014Sroger 108062112Sroger common_bktr_attach(bktr, unit, fun, rev); 108159014Sroger} 108259014Sroger 108359014Sroger 108459014Sroger/* 108559014Sroger * Special Memory Allocation 108659014Sroger */ 108759014Srogervm_offset_t 108859014Srogerget_bktr_mem(bktr, dmapp, size) 108959014Sroger bktr_ptr_t bktr; 109059014Sroger bus_dmamap_t *dmapp; 109159014Sroger unsigned int size; 109259014Sroger{ 109359014Sroger bus_dma_tag_t dmat = bktr->dmat; 109459014Sroger bus_dma_segment_t seg; 109559014Sroger bus_size_t align; 109659014Sroger int rseg; 109759014Sroger caddr_t kva; 109859014Sroger 109959014Sroger /* 110059014Sroger * Allocate a DMA area 110159014Sroger */ 110259014Sroger align = 1 << 24; 110359014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 110459014Sroger &rseg, BUS_DMA_NOWAIT)) { 110559014Sroger align = PAGE_SIZE; 110659014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 110759014Sroger &rseg, BUS_DMA_NOWAIT)) { 110862112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 110962112Sroger bktr_name(bktr), size); 111059014Sroger return 0; 111159014Sroger } 111259014Sroger } 111359014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 111459014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 111562112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 111662112Sroger bktr_name(bktr), size); 111759014Sroger bus_dmamem_free(dmat, &seg, rseg); 111859014Sroger return 0; 111959014Sroger } 112059014Sroger#ifdef __OpenBSD__ 112159014Sroger bktr->dm_mapsize = size; 112259014Sroger#endif 112359014Sroger /* 112459014Sroger * Create and locd the DMA map for the DMA area 112559014Sroger */ 112659014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 112762112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 112862112Sroger bktr_name(bktr), size); 112959014Sroger bus_dmamem_unmap(dmat, kva, size); 113059014Sroger bus_dmamem_free(dmat, &seg, rseg); 113159014Sroger return 0; 113259014Sroger } 113359014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 113462112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 113562112Sroger bktr_name(bktr), size); 113659014Sroger bus_dmamem_unmap(dmat, kva, size); 113759014Sroger bus_dmamem_free(dmat, &seg, rseg); 113859014Sroger bus_dmamap_destroy(dmat, *dmapp); 113959014Sroger return 0; 114059014Sroger } 114159014Sroger return (vm_offset_t)kva; 114259014Sroger} 114359014Sroger 114459014Srogervoid 114559014Srogerfree_bktr_mem(bktr, dmap, kva) 114659014Sroger bktr_ptr_t bktr; 114759014Sroger bus_dmamap_t dmap; 114859014Sroger vm_offset_t kva; 114959014Sroger{ 115059014Sroger bus_dma_tag_t dmat = bktr->dmat; 115159014Sroger 115259014Sroger#ifdef __NetBSD__ 115359014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 115459014Sroger#else 115559014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 115659014Sroger#endif 115759014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 115859014Sroger bus_dmamap_destroy(dmat, dmap); 115959014Sroger} 116059014Sroger 116159014Sroger 116259014Sroger/*--------------------------------------------------------- 116359014Sroger** 116459014Sroger** BrookTree 848 character device driver routines 116559014Sroger** 116659014Sroger**--------------------------------------------------------- 116759014Sroger*/ 116859014Sroger 116959014Sroger 117059014Sroger#define VIDEO_DEV 0x00 117159014Sroger#define TUNER_DEV 0x01 117259014Sroger#define VBI_DEV 0x02 117359014Sroger 117462112Sroger#define UNIT(x) (minor((x) & 0x0f)) 117562112Sroger#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 117659014Sroger 117759014Sroger/* 117859014Sroger * 117959014Sroger */ 118059014Srogerint 118183366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 118259014Sroger{ 118359014Sroger bktr_ptr_t bktr; 118459014Sroger int unit; 118559014Sroger 118662112Sroger unit = UNIT(dev); 118759014Sroger 118859014Sroger /* unit out of range */ 118959014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 119062112Sroger return(ENXIO); 119159014Sroger 119259014Sroger bktr = bktr_cd.cd_devs[unit]; 119359014Sroger 119459014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 119562112Sroger return(ENXIO); 119659014Sroger 119762112Sroger switch (FUNCTION(dev)) { 119859014Sroger case VIDEO_DEV: 119962112Sroger return(video_open(bktr)); 120059014Sroger case TUNER_DEV: 120162112Sroger return(tuner_open(bktr)); 120259014Sroger case VBI_DEV: 120362112Sroger return(vbi_open(bktr)); 120459014Sroger } 120559014Sroger 120662112Sroger return(ENXIO); 120759014Sroger} 120859014Sroger 120959014Sroger 121059014Sroger/* 121159014Sroger * 121259014Sroger */ 121359014Srogerint 121483366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 121559014Sroger{ 121659014Sroger bktr_ptr_t bktr; 121759014Sroger int unit; 121859014Sroger 121962112Sroger unit = UNIT(dev); 122059014Sroger 122159014Sroger bktr = bktr_cd.cd_devs[unit]; 122259014Sroger 122362112Sroger switch (FUNCTION(dev)) { 122459014Sroger case VIDEO_DEV: 122562112Sroger return(video_close(bktr)); 122659014Sroger case TUNER_DEV: 122762112Sroger return(tuner_close(bktr)); 122859014Sroger case VBI_DEV: 122962112Sroger return(vbi_close(bktr)); 123059014Sroger } 123159014Sroger 123262112Sroger return(ENXIO); 123359014Sroger} 123459014Sroger 123559014Sroger/* 123659014Sroger * 123759014Sroger */ 123859014Srogerint 123962112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 124059014Sroger{ 124159014Sroger bktr_ptr_t bktr; 124259014Sroger int unit; 124359014Sroger 124462112Sroger unit = UNIT(dev); 124559014Sroger 124659014Sroger bktr = bktr_cd.cd_devs[unit]; 124759014Sroger 124862112Sroger switch (FUNCTION(dev)) { 124959014Sroger case VIDEO_DEV: 125062112Sroger return(video_read(bktr, unit, dev, uio)); 125159014Sroger case VBI_DEV: 125262112Sroger return(vbi_read(bktr, uio, ioflag)); 125359014Sroger } 125459014Sroger 125562112Sroger return(ENXIO); 125659014Sroger} 125759014Sroger 125859014Sroger 125959014Sroger/* 126059014Sroger * 126159014Sroger */ 126259014Srogerint 126362112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 126459014Sroger{ 126559014Sroger /* operation not supported */ 126662112Sroger return(EOPNOTSUPP); 126759014Sroger} 126859014Sroger 126959014Sroger/* 127059014Sroger * 127159014Sroger */ 127259014Srogerint 127383366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 127459014Sroger{ 127559014Sroger bktr_ptr_t bktr; 127659014Sroger int unit; 127759014Sroger 127862112Sroger unit = UNIT(dev); 127959014Sroger 128059014Sroger bktr = bktr_cd.cd_devs[unit]; 128159014Sroger 128259014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 128362112Sroger return(ENOMEM); 128459014Sroger 128562112Sroger switch (FUNCTION(dev)) { 128659014Sroger case VIDEO_DEV: 128762112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 128859014Sroger case TUNER_DEV: 128962112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 129059014Sroger } 129159014Sroger 129262112Sroger return(ENXIO); 129359014Sroger} 129459014Sroger 129559014Sroger/* 129659014Sroger * 129759014Sroger */ 129862214Srogerpaddr_t 129962214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 130059014Sroger{ 130159014Sroger int unit; 130259014Sroger bktr_ptr_t bktr; 130359014Sroger 130462112Sroger unit = UNIT(dev); 130559014Sroger 130662112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 130762112Sroger return(-1); 130859014Sroger 130959014Sroger bktr = bktr_cd.cd_devs[unit]; 131059014Sroger 131162112Sroger if ((vaddr_t)offset < 0) 131262112Sroger return(-1); 131359014Sroger 131462112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 131562112Sroger return(-1); 131659014Sroger 131759014Sroger#ifdef __NetBSD__ 131859014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 131962112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 132059014Sroger#else 132162112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 132259014Sroger#endif 132359014Sroger} 132459014Sroger 132551694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1326