bktr_os.c revision 115556
151694Sroger/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 115556 2003-05-31 20:41:52Z phk $ */ 251694Sroger 351694Sroger/* 451694Sroger * This is part of the Driver for Video Capture Cards (Frame grabbers) 551694Sroger * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 651694Sroger * chipset. 751694Sroger * Copyright Roger Hardiman and Amancio Hasty. 851694Sroger * 951694Sroger * bktr_os : This has all the Operating System dependant code, 1051694Sroger * probe/attach and open/close/ioctl/read/mmap 1151694Sroger * memory allocation 1251694Sroger * PCI bus interfacing 1351694Sroger * 1451694Sroger * 1551694Sroger */ 1651694Sroger 1751694Sroger/* 1851694Sroger * 1. Redistributions of source code must retain the 1951694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 2051694Sroger * All rights reserved. 2151694Sroger * 2251694Sroger * Redistribution and use in source and binary forms, with or without 2351694Sroger * modification, are permitted provided that the following conditions 2451694Sroger * are met: 2551694Sroger * 1. Redistributions of source code must retain the above copyright 2651694Sroger * notice, this list of conditions and the following disclaimer. 2751694Sroger * 2. Redistributions in binary form must reproduce the above copyright 2851694Sroger * notice, this list of conditions and the following disclaimer in the 2951694Sroger * documentation and/or other materials provided with the distribution. 3051694Sroger * 3. All advertising materials mentioning features or use of this software 3151694Sroger * must display the following acknowledgement: 3251694Sroger * This product includes software developed by Amancio Hasty and 3351694Sroger * Roger Hardiman 3451694Sroger * 4. The name of the author may not be used to endorse or promote products 3551694Sroger * derived from this software without specific prior written permission. 3651694Sroger * 3751694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 3851694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3951694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 4051694Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 4151694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 4251694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 4351694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4451694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4551694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 4651694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4751694Sroger * POSSIBILITY OF SUCH DAMAGE. 4851694Sroger */ 4951694Sroger 5051694Sroger 5159014Sroger#include "opt_bktr.h" /* include any kernel config options */ 5251694Sroger 5351694Sroger#define FIFO_RISC_DISABLED 0 5451694Sroger#define ALL_INTS_DISABLED 0 5551694Sroger 5662214Sroger 5762214Sroger/*******************/ 5862214Sroger/* *** FreeBSD *** */ 5962214Sroger/*******************/ 6062214Sroger#ifdef __FreeBSD__ 6162214Sroger 6251694Sroger#include <sys/param.h> 6351694Sroger#include <sys/systm.h> 6451694Sroger#include <sys/conf.h> 6551694Sroger#include <sys/uio.h> 6651694Sroger#include <sys/kernel.h> 6751694Sroger#include <sys/signalvar.h> 6851694Sroger#include <sys/mman.h> 6951694Sroger#include <sys/poll.h> 7070834Swollman#if __FreeBSD_version >= 500014 7170834Swollman#include <sys/selinfo.h> 7270834Swollman#else 7351694Sroger#include <sys/select.h> 7470834Swollman#endif 7551694Sroger#include <sys/vnode.h> 7651694Sroger 7751694Sroger#include <vm/vm.h> 7851694Sroger#include <vm/vm_kern.h> 7951694Sroger#include <vm/pmap.h> 8051694Sroger#include <vm/vm_extern.h> 8151694Sroger 8293023Snsouch#if (__FreeBSD_version >=400000) 8351694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 8451694Sroger#endif 8551694Sroger 8659014Sroger#if (__FreeBSD_version >=300000) 8759014Sroger#include <machine/bus_memio.h> /* used by bus space */ 8859014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 8959014Sroger#include <sys/bus.h> 9059014Sroger#endif 9159014Sroger 9251694Sroger#if (__FreeBSD_version >=400000) 9351694Sroger#include <sys/rman.h> /* used by newbus */ 9451694Sroger#include <machine/resource.h> /* used by newbus */ 9551694Sroger#endif 9651694Sroger 9767306Sroger#if (__FreeBSD_version < 500000) 9867306Sroger#include <machine/clock.h> /* for DELAY */ 9967306Sroger#endif 10059014Sroger 10151694Sroger#include <pci/pcivar.h> 10251694Sroger#include <pci/pcireg.h> 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; 11051694Sroger 11151694SrogerSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 11251694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 11351694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 11451694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 11551694SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 11659014SrogerSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 11751694Sroger 11862214Sroger#endif /* end freebsd section */ 11951694Sroger 12062214Sroger 12162214Sroger 12251694Sroger/****************/ 12351694Sroger/* *** BSDI *** */ 12451694Sroger/****************/ 12551694Sroger#ifdef __bsdi__ 12651694Sroger#endif /* __bsdi__ */ 12751694Sroger 12851694Sroger 12951694Sroger/**************************/ 13051694Sroger/* *** OpenBSD/NetBSD *** */ 13151694Sroger/**************************/ 13251694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 13362214Sroger 13462214Sroger#include <sys/param.h> 13562214Sroger#include <sys/systm.h> 13662214Sroger#include <sys/conf.h> 13762214Sroger#include <sys/uio.h> 13862214Sroger#include <sys/kernel.h> 13962214Sroger#include <sys/signalvar.h> 14062214Sroger#include <sys/mman.h> 14162214Sroger#include <sys/poll.h> 14262214Sroger#include <sys/select.h> 14362214Sroger#include <sys/vnode.h> 14462214Sroger 14562214Sroger#include <vm/vm.h> 14662214Sroger 14762214Sroger#ifndef __NetBSD__ 14862214Sroger#include <vm/vm_kern.h> 14962214Sroger#include <vm/pmap.h> 15062214Sroger#include <vm/vm_extern.h> 15162214Sroger#endif 15262214Sroger 15359014Sroger#include <sys/device.h> 15459014Sroger#include <dev/pci/pcivar.h> 15559014Sroger#include <dev/pci/pcireg.h> 15659014Sroger#include <dev/pci/pcidevs.h> 15759014Sroger 15859014Sroger#define BKTR_DEBUG 15959014Sroger#ifdef BKTR_DEBUG 16059014Srogerint bktr_debug = 0; 16159014Sroger#define DPR(x) (bktr_debug ? printf x : 0) 16259014Sroger#else 16359014Sroger#define DPR(x) 16459014Sroger#endif 16551694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 16651694Sroger 16751694Sroger 16862214Sroger#ifdef __NetBSD__ 16962214Sroger#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 17062214Sroger#include <dev/pci/bktr/bktr_reg.h> 17162214Sroger#include <dev/pci/bktr/bktr_tuner.h> 17262214Sroger#include <dev/pci/bktr/bktr_card.h> 17362214Sroger#include <dev/pci/bktr/bktr_audio.h> 17462214Sroger#include <dev/pci/bktr/bktr_core.h> 17562214Sroger#include <dev/pci/bktr/bktr_os.h> 17662214Sroger#else /* Traditional location for .h files */ 17762214Sroger#include <machine/ioctl_meteor.h> 17862214Sroger#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 17962214Sroger#include <dev/bktr/bktr_reg.h> 18062214Sroger#include <dev/bktr/bktr_tuner.h> 18162214Sroger#include <dev/bktr/bktr_card.h> 18262214Sroger#include <dev/bktr/bktr_audio.h> 18362214Sroger#include <dev/bktr/bktr_core.h> 18462214Sroger#include <dev/bktr/bktr_os.h> 18593023Snsouch 18665692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 18765392Speter#include <dev/bktr/bktr_i2c.h> 18893023Snsouch 18993023Snsouch#include "iicbb_if.h" 19093023Snsouch#include "smbus_if.h" 19162214Sroger#endif 19265392Speter#endif 19351694Sroger 19462214Sroger 19551694Sroger/****************************/ 19651694Sroger/* *** FreeBSD 4.x code *** */ 19751694Sroger/****************************/ 19851694Sroger#if (__FreeBSD_version >= 400000) 19951694Sroger 20051694Srogerstatic int bktr_probe( device_t dev ); 20151694Srogerstatic int bktr_attach( device_t dev ); 20251694Srogerstatic int bktr_detach( device_t dev ); 20351694Srogerstatic int bktr_shutdown( device_t dev ); 20451694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 20551694Sroger 20651694Srogerstatic device_method_t bktr_methods[] = { 20751694Sroger /* Device interface */ 20851694Sroger DEVMETHOD(device_probe, bktr_probe), 20951694Sroger DEVMETHOD(device_attach, bktr_attach), 21051694Sroger DEVMETHOD(device_detach, bktr_detach), 21151694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 21251694Sroger 21393023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 21493023Snsouch /* iicbb interface */ 21593023Snsouch DEVMETHOD(iicbb_callback, bti2c_iic_callback), 21693023Snsouch DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 21793023Snsouch DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 21893023Snsouch DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 21993023Snsouch DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 22093023Snsouch DEVMETHOD(iicbb_reset, bti2c_iic_reset), 22193023Snsouch 22293023Snsouch /* smbus interface */ 22393023Snsouch DEVMETHOD(smbus_callback, bti2c_smb_callback), 22493023Snsouch DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 22593023Snsouch DEVMETHOD(smbus_writew, bti2c_smb_writew), 22693023Snsouch DEVMETHOD(smbus_readb, bti2c_smb_readb), 22793023Snsouch#endif 22893023Snsouch 22951694Sroger { 0, 0 } 23051694Sroger}; 23151694Sroger 23251694Srogerstatic driver_t bktr_driver = { 23351694Sroger "bktr", 23451694Sroger bktr_methods, 23551694Sroger sizeof(struct bktr_softc), 23651694Sroger}; 23751694Sroger 23851694Srogerstatic devclass_t bktr_devclass; 23951694Sroger 24051694Srogerstatic d_open_t bktr_open; 24151694Srogerstatic d_close_t bktr_close; 24251694Srogerstatic d_read_t bktr_read; 24351694Srogerstatic d_write_t bktr_write; 24451694Srogerstatic d_ioctl_t bktr_ioctl; 24551694Srogerstatic d_mmap_t bktr_mmap; 24651694Srogerstatic d_poll_t bktr_poll; 24751694Sroger 24851694Sroger#define CDEV_MAJOR 92 24951694Srogerstatic struct cdevsw bktr_cdevsw = { 250111815Sphk .d_open = bktr_open, 251111815Sphk .d_close = bktr_close, 252111815Sphk .d_read = bktr_read, 253111815Sphk .d_write = bktr_write, 254111815Sphk .d_ioctl = bktr_ioctl, 255111815Sphk .d_poll = bktr_poll, 256111815Sphk .d_mmap = bktr_mmap, 257111815Sphk .d_name = "bktr", 258111815Sphk .d_maj = CDEV_MAJOR, 25951694Sroger}; 26051694Sroger 26152995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 26267306Sroger#if (__FreeBSD_version > 410000) 26365728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 26465728SrogerMODULE_VERSION(bktr, 1); 26567306Sroger#endif 26651694Sroger 26751694Sroger 26851694Sroger/* 26951694Sroger * the boot time probe routine. 27051694Sroger */ 27151694Srogerstatic int 27251694Srogerbktr_probe( device_t dev ) 27351694Sroger{ 27451694Sroger unsigned int type = pci_get_devid(dev); 27551694Sroger unsigned int rev = pci_get_revid(dev); 27651694Sroger 27767306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 27867306Sroger { 27967306Sroger switch (PCI_PRODUCT(type)) { 28067306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 28167306Sroger if (rev == 0x12) 28267306Sroger device_set_desc(dev, "BrookTree 848A"); 28367306Sroger else 28467306Sroger device_set_desc(dev, "BrookTree 848"); 28567306Sroger return 0; 28667306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 28767306Sroger device_set_desc(dev, "BrookTree 849A"); 28867306Sroger return 0; 28967306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 29067306Sroger device_set_desc(dev, "BrookTree 878"); 29167306Sroger return 0; 29267306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 29367306Sroger device_set_desc(dev, "BrookTree 879"); 29467306Sroger return 0; 29567306Sroger } 29651694Sroger }; 29751694Sroger 29851694Sroger return ENXIO; 29951694Sroger} 30051694Sroger 30151694Sroger 30251694Sroger/* 30351694Sroger * the attach routine. 30451694Sroger */ 30551694Srogerstatic int 30651694Srogerbktr_attach( device_t dev ) 30751694Sroger{ 30851694Sroger u_long latency; 30951694Sroger u_long fun; 31051694Sroger u_long val; 31151694Sroger unsigned int rev; 31251694Sroger unsigned int unit; 31351694Sroger int error = 0; 31451694Sroger#ifdef BROOKTREE_IRQ 31551694Sroger u_long old_irq, new_irq; 31651694Sroger#endif 31751694Sroger 31851694Sroger struct bktr_softc *bktr = device_get_softc(dev); 31951694Sroger 32051694Sroger unit = device_get_unit(dev); 32151694Sroger 32262112Sroger /* build the device name for bktr_name() */ 32362112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 32462112Sroger 32551694Sroger /* 32651694Sroger * Enable bus mastering and Memory Mapped device 32751694Sroger */ 32851694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 32951694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 33051694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 33151694Sroger 33251694Sroger /* 33351694Sroger * Map control/status registers. 33451694Sroger */ 33565049Sroger bktr->mem_rid = PCIR_MAPS; 33665049Sroger bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 33765049Sroger 0, ~0, 1, RF_ACTIVE); 33851694Sroger 33965049Sroger 34051694Sroger if (!bktr->res_mem) { 34151694Sroger device_printf(dev, "could not map memory\n"); 34251694Sroger error = ENXIO; 34351694Sroger goto fail; 34451694Sroger } 34559014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 34659014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 34751694Sroger 34859014Sroger 34951694Sroger /* 35051694Sroger * Disable the brooktree device 35151694Sroger */ 35259014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 35359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 35451694Sroger 35551694Sroger 35651694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 35751694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 35851694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 35951694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36051694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 36151694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 36251694Sroger#endif 36351694Sroger 36451694Sroger /* 36551694Sroger * Allocate our interrupt. 36651694Sroger */ 36765049Sroger bktr->irq_rid = 0; 36865049Sroger bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 36965049Sroger 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 37051694Sroger if (bktr->res_irq == NULL) { 37151694Sroger device_printf(dev, "could not map interrupt\n"); 37251694Sroger error = ENXIO; 37351694Sroger goto fail; 37451694Sroger } 37551694Sroger 37659250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 37751694Sroger bktr_intr, bktr, &bktr->res_ih); 37851694Sroger if (error) { 37951694Sroger device_printf(dev, "could not setup irq\n"); 38051694Sroger goto fail; 38151694Sroger 38251694Sroger } 38351694Sroger 38451694Sroger 38551694Sroger /* Update the Device Control Register */ 38651694Sroger /* on Bt878 and Bt879 cards */ 38751694Sroger fun = pci_read_config( dev, 0x40, 2); 38851694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 38951694Sroger 39051694Sroger#if defined( BKTR_430_FX_MODE ) 39151694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 39251694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 39351694Sroger#endif 39451694Sroger 39551694Sroger#if defined( BKTR_SIS_VIA_MODE ) 39651694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 39751694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 39851694Sroger OPTi chipset motherboards too */ 39951694Sroger#endif 40051694Sroger pci_write_config(dev, 0x40, fun, 2); 40151694Sroger 40265692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 40393023Snsouch if (bt848_i2c_attach(dev)) 40451694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 40551694Sroger#endif 40651694Sroger 40751694Sroger/* 40851694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 40951694Sroger * you have more than four, then 16 would probably be a better value. 41051694Sroger */ 41151694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 41251694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 41351694Sroger#endif 41451694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 41551694Sroger latency = (latency >> 8) & 0xff; 41651694Sroger if ( bootverbose ) { 41751694Sroger if (latency) 41851694Sroger printf("brooktree%d: PCI bus latency is", unit); 41951694Sroger else 42051694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 42151694Sroger unit); 42251694Sroger } 42351694Sroger if ( !latency ) { 42451694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 42551694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 42651694Sroger } 42751694Sroger if ( bootverbose ) { 42851694Sroger printf(" %d.\n", (int) latency); 42951694Sroger } 43051694Sroger 43151694Sroger /* read the pci device id and revision id */ 43251694Sroger fun = pci_get_devid(dev); 43351694Sroger rev = pci_get_revid(dev); 43451694Sroger 43551694Sroger /* call the common attach code */ 43651694Sroger common_bktr_attach( bktr, unit, fun, rev ); 43751694Sroger 43867306Sroger /* make the device entries */ 43967306Sroger bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 44067306Sroger 0, 0, 0444, "bktr%d", unit); 44167306Sroger bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 44267306Sroger 0, 0, 0444, "tuner%d", unit); 44367306Sroger bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 44467306Sroger 0, 0, 0444, "vbi%d" , unit); 44551694Sroger 44667306Sroger 44767306Sroger /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 44867306Sroger /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 44967306Sroger#if (__FreeBSD_version >=500000) 45067306Sroger if (unit == 0) { 45167306Sroger bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 45267306Sroger bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 45367306Sroger bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 45467306Sroger } 45567306Sroger#endif 45667306Sroger 45751694Sroger return 0; 45851694Sroger 45951694Srogerfail: 46065049Sroger if (bktr->res_irq) 46165049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 46265049Sroger if (bktr->res_mem) 46365049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 46451694Sroger return error; 46551694Sroger 46651694Sroger} 46751694Sroger 46851694Sroger/* 46951694Sroger * the detach routine. 47051694Sroger */ 47151694Srogerstatic int 47251694Srogerbktr_detach( device_t dev ) 47351694Sroger{ 47451694Sroger struct bktr_softc *bktr = device_get_softc(dev); 47551694Sroger 47651694Sroger /* Disable the brooktree device */ 47759014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 47859014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 47951694Sroger 48093023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 48193023Snsouch if (bt848_i2c_detach(dev)) 482115556Sphk printf("bktr%d: i2c_attach: can't attach\n", 483115556Sphk device_get_unit(dev)); 48493023Snsouch#endif 48593023Snsouch 48667306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 48767306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 48867306Sroger /* then reload the main bktr driver module */ 48951694Sroger 490107699Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices, 491107699Sroger * the aliases for unit 0 are automatically destroyed */ 49267306Sroger destroy_dev(bktr->vbidev); 49367306Sroger destroy_dev(bktr->tunerdev); 49467306Sroger destroy_dev(bktr->bktrdev); 49567306Sroger 49651694Sroger /* 49751694Sroger * Deallocate resources. 49851694Sroger */ 49951694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 50065049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 50165049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 50265049Sroger 50351694Sroger return 0; 50451694Sroger} 50551694Sroger 50651694Sroger/* 50751694Sroger * the shutdown routine. 50851694Sroger */ 50951694Srogerstatic int 51051694Srogerbktr_shutdown( device_t dev ) 51151694Sroger{ 51251694Sroger struct bktr_softc *bktr = device_get_softc(dev); 51351694Sroger 51451694Sroger /* Disable the brooktree device */ 51559014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 51659014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 51751694Sroger 51851694Sroger return 0; 51951694Sroger} 52051694Sroger 52151694Sroger 52251694Sroger/* 52351694Sroger * Special Memory Allocation 52451694Sroger */ 52551694Srogervm_offset_t 52651694Srogerget_bktr_mem( int unit, unsigned size ) 52751694Sroger{ 52851694Sroger vm_offset_t addr = 0; 52951694Sroger 53051694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 53151694Sroger if (addr == 0) 53251694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 53351694Sroger if (addr == 0) { 53451694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 53551694Sroger unit, size); 53651694Sroger } 53751694Sroger 53851694Sroger return( addr ); 53951694Sroger} 54051694Sroger 54151694Sroger 54251694Sroger/*--------------------------------------------------------- 54351694Sroger** 54451694Sroger** BrookTree 848 character device driver routines 54551694Sroger** 54651694Sroger**--------------------------------------------------------- 54751694Sroger*/ 54851694Sroger 54951694Sroger#define VIDEO_DEV 0x00 55051694Sroger#define TUNER_DEV 0x01 55151694Sroger#define VBI_DEV 0x02 55251694Sroger 55351694Sroger#define UNIT(x) ((x) & 0x0f) 55451694Sroger#define FUNCTION(x) (x >> 4) 55551694Sroger 55651694Sroger/* 55751694Sroger * 55851694Sroger */ 559104094Sphkstatic int 56083366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 56151694Sroger{ 56251694Sroger bktr_ptr_t bktr; 56351694Sroger int unit; 56451694Sroger int result; 56551694Sroger 56651694Sroger unit = UNIT( minor(dev) ); 56751694Sroger 56851694Sroger /* Get the device data */ 56951694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 57051694Sroger if (bktr == NULL) { 57151694Sroger /* the device is no longer valid/functioning */ 57251694Sroger return (ENXIO); 57351694Sroger } 57451694Sroger 57551694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 57651694Sroger return( ENXIO ); 57751694Sroger 57851694Sroger /* Record that the device is now busy */ 57951694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 58051694Sroger 58151694Sroger 58251694Sroger if (bt848_card != -1) { 58351694Sroger if ((bt848_card >> 8 == unit ) && 58451694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 58551694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 58651694Sroger bktr->bt848_card = (bt848_card & 0xff); 58751694Sroger probeCard(bktr, FALSE, unit); 58851694Sroger } 58951694Sroger } 59051694Sroger } 59151694Sroger 59251694Sroger if (bt848_tuner != -1) { 59351694Sroger if ((bt848_tuner >> 8 == unit ) && 59451694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 59551694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 59651694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 59751694Sroger probeCard(bktr, FALSE, unit); 59851694Sroger } 59951694Sroger } 60051694Sroger } 60151694Sroger 60251694Sroger if (bt848_reverse_mute != -1) { 60359014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 60451694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 60551694Sroger } 60651694Sroger } 60751694Sroger 60859014Sroger if (bt848_slow_msp_audio != -1) { 60959014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 61059014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 61159014Sroger } 61259014Sroger } 61359014Sroger 61451694Sroger switch ( FUNCTION( minor(dev) ) ) { 61551694Sroger case VIDEO_DEV: 61651694Sroger result = video_open( bktr ); 61751694Sroger break; 61851694Sroger case TUNER_DEV: 61951694Sroger result = tuner_open( bktr ); 62051694Sroger break; 62151694Sroger case VBI_DEV: 62251694Sroger result = vbi_open( bktr ); 62351694Sroger break; 62451694Sroger default: 62551694Sroger result = ENXIO; 62651694Sroger break; 62751694Sroger } 62851694Sroger 62951694Sroger /* If there was an error opening the device, undo the busy status */ 63051694Sroger if (result != 0) 63151694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 63251694Sroger return( result ); 63351694Sroger} 63451694Sroger 63551694Sroger 63651694Sroger/* 63751694Sroger * 63851694Sroger */ 639104094Sphkstatic int 64083366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 64151694Sroger{ 64251694Sroger bktr_ptr_t bktr; 64351694Sroger int unit; 64451694Sroger int result; 64551694Sroger 64651694Sroger unit = UNIT( minor(dev) ); 64751694Sroger 64851694Sroger /* Get the device data */ 64951694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 65051694Sroger if (bktr == NULL) { 65151694Sroger /* the device is no longer valid/functioning */ 65251694Sroger return (ENXIO); 65351694Sroger } 65451694Sroger 65551694Sroger switch ( FUNCTION( minor(dev) ) ) { 65651694Sroger case VIDEO_DEV: 65751694Sroger result = video_close( bktr ); 65851694Sroger break; 65951694Sroger case TUNER_DEV: 66051694Sroger result = tuner_close( bktr ); 66151694Sroger break; 66251694Sroger case VBI_DEV: 66351694Sroger result = vbi_close( bktr ); 66451694Sroger break; 66551694Sroger default: 66651694Sroger return (ENXIO); 66751694Sroger break; 66851694Sroger } 66951694Sroger 67051694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 67151694Sroger return( result ); 67251694Sroger} 67351694Sroger 67451694Sroger 67551694Sroger/* 67651694Sroger * 67751694Sroger */ 678104094Sphkstatic int 67951694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 68051694Sroger{ 68151694Sroger bktr_ptr_t bktr; 68251694Sroger int unit; 68351694Sroger 68451694Sroger unit = UNIT(minor(dev)); 68551694Sroger 68651694Sroger /* Get the device data */ 68751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 68851694Sroger if (bktr == NULL) { 68951694Sroger /* the device is no longer valid/functioning */ 69051694Sroger return (ENXIO); 69151694Sroger } 69251694Sroger 69351694Sroger switch ( FUNCTION( minor(dev) ) ) { 69451694Sroger case VIDEO_DEV: 69551694Sroger return( video_read( bktr, unit, dev, uio ) ); 69651694Sroger case VBI_DEV: 69751694Sroger return( vbi_read( bktr, uio, ioflag ) ); 69851694Sroger } 69951694Sroger return( ENXIO ); 70051694Sroger} 70151694Sroger 70251694Sroger 70351694Sroger/* 70451694Sroger * 70551694Sroger */ 706104094Sphkstatic int 70751694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 70851694Sroger{ 70951694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 71051694Sroger} 71151694Sroger 71251694Sroger 71351694Sroger/* 71451694Sroger * 71551694Sroger */ 716104094Sphkstatic int 71783366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 71851694Sroger{ 71951694Sroger bktr_ptr_t bktr; 72051694Sroger int unit; 72151694Sroger 72251694Sroger unit = UNIT(minor(dev)); 72351694Sroger 72451694Sroger /* Get the device data */ 72551694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 72651694Sroger if (bktr == NULL) { 72751694Sroger /* the device is no longer valid/functioning */ 72851694Sroger return (ENXIO); 72951694Sroger } 73051694Sroger 73151694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 73251694Sroger return( ENOMEM ); 73351694Sroger 73451694Sroger switch ( FUNCTION( minor(dev) ) ) { 73551694Sroger case VIDEO_DEV: 73683366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 73751694Sroger case TUNER_DEV: 73883366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 73951694Sroger } 74051694Sroger 74151694Sroger return( ENXIO ); 74251694Sroger} 74351694Sroger 74451694Sroger 74551694Sroger/* 74651694Sroger * 74751694Sroger */ 748104094Sphkstatic int 749112569Sjakebktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 75051694Sroger{ 75151694Sroger int unit; 75251694Sroger bktr_ptr_t bktr; 75351694Sroger 75451694Sroger unit = UNIT(minor(dev)); 75551694Sroger 75651694Sroger if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 75751694Sroger return( -1 ); 75851694Sroger 75951694Sroger /* Get the device data */ 76051694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76151694Sroger if (bktr == NULL) { 76251694Sroger /* the device is no longer valid/functioning */ 76351694Sroger return (ENXIO); 76451694Sroger } 76551694Sroger 76651694Sroger if (nprot & PROT_EXEC) 76751694Sroger return( -1 ); 76851694Sroger 76951694Sroger if (offset < 0) 77051694Sroger return( -1 ); 77151694Sroger 77251694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 77351694Sroger return( -1 ); 77451694Sroger 775111462Smux *paddr = vtophys(bktr->bigbuf) + offset; 776111462Smux return( 0 ); 77751694Sroger} 77851694Sroger 779104094Sphkstatic int 780104094Sphkbktr_poll( dev_t dev, int events, struct thread *td) 78151694Sroger{ 78251694Sroger int unit; 78351694Sroger bktr_ptr_t bktr; 78451694Sroger int revents = 0; 78559277Sroger DECLARE_INTR_MASK(s); 78651694Sroger 78751694Sroger unit = UNIT(minor(dev)); 78851694Sroger 78951694Sroger /* Get the device data */ 79051694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 79151694Sroger if (bktr == NULL) { 79251694Sroger /* the device is no longer valid/functioning */ 79351694Sroger return (ENXIO); 79451694Sroger } 79551694Sroger 79659277Sroger DISABLE_INTR(s); 79751694Sroger 79851694Sroger if (events & (POLLIN | POLLRDNORM)) { 79951694Sroger 80051694Sroger switch ( FUNCTION( minor(dev) ) ) { 80151694Sroger case VBI_DEV: 80251694Sroger if(bktr->vbisize == 0) 80383366Sjulian selrecord(td, &bktr->vbi_select); 80451694Sroger else 80551694Sroger revents |= events & (POLLIN | POLLRDNORM); 80651694Sroger break; 80751694Sroger } 80851694Sroger } 80951694Sroger 81059250Sroger ENABLE_INTR(s); 81151694Sroger 81251694Sroger return (revents); 81351694Sroger} 81451694Sroger 81551694Sroger#endif /* FreeBSD 4.x specific kernel interface routines */ 81651694Sroger 81751694Sroger/*****************/ 81851694Sroger/* *** BSDI *** */ 81951694Sroger/*****************/ 82051694Sroger 82151694Sroger#if defined(__bsdi__) 82251694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 82351694Sroger 82451694Sroger 82551694Sroger/*****************************/ 82651694Sroger/* *** OpenBSD / NetBSD *** */ 82751694Sroger/*****************************/ 82851694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 82959014Sroger 83059014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 83159014Sroger 83259014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 83359014Sroger 83459014Sroger#define bktr_open bktropen 83559014Sroger#define bktr_close bktrclose 83659014Sroger#define bktr_read bktrread 83759014Sroger#define bktr_write bktrwrite 83859014Sroger#define bktr_ioctl bktrioctl 83959014Sroger#define bktr_mmap bktrmmap 84059014Sroger 84159014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 84259014Sroger vm_offset_t, vm_offset_t); 84359014Sroger 84462112Sroger#if defined(__OpenBSD__) 84592739Salfredstatic int bktr_probe(struct device *, void *, void *); 84659014Sroger#else 84792739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 84859014Sroger#endif 84992739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 85059014Sroger 85159014Srogerstruct cfattach bktr_ca = { 85259014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 85359014Sroger}; 85459014Sroger 85559014Sroger#if defined(__NetBSD__) 85659014Srogerextern struct cfdriver bktr_cd; 85759014Sroger#else 85859014Srogerstruct cfdriver bktr_cd = { 85959014Sroger NULL, "bktr", DV_DULL 86059014Sroger}; 86159014Sroger#endif 86259014Sroger 86362112Srogerint 86462112Srogerbktr_probe(parent, match, aux) 86562112Sroger struct device *parent; 86662112Sroger#if defined(__OpenBSD__) 86759014Sroger void *match; 86859014Sroger#else 86959014Sroger struct cfdata *match; 87059014Sroger#endif 87159014Sroger void *aux; 87259014Sroger{ 87359014Sroger struct pci_attach_args *pa = aux; 87459014Sroger 87559014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 87659014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 87759014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 87859014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 87959014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 88059014Sroger return 1; 88159014Sroger 88259014Sroger return 0; 88359014Sroger} 88459014Sroger 88559014Sroger 88659014Sroger/* 88759014Sroger * the attach routine. 88859014Sroger */ 88959014Srogerstatic void 89062112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 89159014Sroger{ 89259014Sroger bktr_ptr_t bktr; 89359014Sroger u_long latency; 89459014Sroger u_long fun; 89559014Sroger unsigned int rev; 89659014Sroger 89759014Sroger#if defined(__OpenBSD__) 89859014Sroger struct pci_attach_args *pa = aux; 89959014Sroger pci_chipset_tag_t pc = pa->pa_pc; 90059014Sroger 90159014Sroger pci_intr_handle_t ih; 90259014Sroger const char *intrstr; 90359014Sroger int retval; 90459014Sroger int unit; 90559014Sroger 90659014Sroger bktr = (bktr_ptr_t)self; 90759014Sroger unit = bktr->bktr_dev.dv_unit; 90859014Sroger 90959014Sroger bktr->pc = pa->pa_pc; 91059014Sroger bktr->tag = pa->pa_tag; 91159014Sroger bktr->dmat = pa->pa_dmat; 91259014Sroger 91359014Sroger /* 91459014Sroger * map memory 91559014Sroger */ 91659014Sroger bktr->memt = pa->pa_memt; 91759014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 91859014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 91959014Sroger if (!retval) 92059014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 92159014Sroger bktr->obmemsz, 0, &bktr->memh); 92259014Sroger if (retval) { 92359014Sroger printf(": couldn't map memory\n"); 92459014Sroger return; 92559014Sroger } 92659014Sroger 92759014Sroger 92859014Sroger /* 92959014Sroger * map interrupt 93059014Sroger */ 93159014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 93259014Sroger pa->pa_intrline, &ih)) { 93359014Sroger printf(": couldn't map interrupt\n"); 93459014Sroger return; 93559014Sroger } 93659014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 93759014Sroger 93859014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 93959014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 94059014Sroger if (bktr->ih == NULL) { 94159014Sroger printf(": couldn't establish interrupt"); 94259014Sroger if (intrstr != NULL) 94359014Sroger printf(" at %s", intrstr); 94459014Sroger printf("\n"); 94559014Sroger return; 94659014Sroger } 94759014Sroger 94859014Sroger if (intrstr != NULL) 94959014Sroger printf(": %s\n", intrstr); 95059014Sroger#endif /* __OpenBSD__ */ 95159014Sroger 95259014Sroger#if defined(__NetBSD__) 95359014Sroger struct pci_attach_args *pa = aux; 95459014Sroger pci_intr_handle_t ih; 95559014Sroger const char *intrstr; 95659014Sroger int retval; 95759014Sroger int unit; 95859014Sroger 95959014Sroger bktr = (bktr_ptr_t)self; 96059014Sroger unit = bktr->bktr_dev.dv_unit; 96159014Sroger bktr->dmat = pa->pa_dmat; 96259014Sroger 96359014Sroger printf("\n"); 96459014Sroger 96559014Sroger /* 96659014Sroger * map memory 96759014Sroger */ 96859014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 96962112Sroger PCI_MAPREG_TYPE_MEM 97062112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 97162112Sroger &bktr->memt, &bktr->memh, NULL, 97262112Sroger &bktr->obmemsz); 97362112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 97462112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 97559014Sroger if (retval) { 97662112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 97759014Sroger return; 97859014Sroger } 97959014Sroger 98059014Sroger /* 98159014Sroger * Disable the brooktree device 98259014Sroger */ 98359014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 98459014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 98559014Sroger 98659014Sroger /* 98759014Sroger * map interrupt 98859014Sroger */ 98959014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 99059014Sroger pa->pa_intrline, &ih)) { 99162112Sroger printf("%s: couldn't map interrupt\n", 99262112Sroger bktr_name(bktr)); 99359014Sroger return; 99459014Sroger } 99559014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 99659014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 99759014Sroger bktr_intr, bktr); 99859014Sroger if (bktr->ih == NULL) { 99959014Sroger printf("%s: couldn't establish interrupt", 100062112Sroger bktr_name(bktr)); 100162112Sroger if (intrstr != NULL) 100262112Sroger printf(" at %s", intrstr); 100362112Sroger printf("\n"); 100462112Sroger return; 100559014Sroger } 100659014Sroger if (intrstr != NULL) 100762112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 100859014Sroger intrstr); 100959014Sroger#endif /* __NetBSD__ */ 101059014Sroger 101159014Sroger/* 101259014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 101359014Sroger * you have more than four, then 16 would probably be a better value. 101459014Sroger */ 101559014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 101659014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 101759014Sroger#endif 101859014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 101959014Sroger latency = (latency >> 8) & 0xff; 102059014Sroger 102162112Sroger if (!latency) { 102262112Sroger if (bootverbose) { 102359014Sroger printf("%s: PCI bus latency was 0 changing to %d", 102462112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 102559014Sroger } 102659014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 102759014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 102859014Sroger PCI_LATENCY_TIMER, latency<<8); 102959014Sroger } 103059014Sroger 103159014Sroger 103262112Sroger /* Enabled Bus Master 103362112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 103462112Sroger boot) */ 103559014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 103662112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 103762112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 103859014Sroger 103959014Sroger /* read the pci id and determine the card type */ 104059014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 104159014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 104259014Sroger 104362112Sroger common_bktr_attach(bktr, unit, fun, rev); 104459014Sroger} 104559014Sroger 104659014Sroger 104759014Sroger/* 104859014Sroger * Special Memory Allocation 104959014Sroger */ 105059014Srogervm_offset_t 105159014Srogerget_bktr_mem(bktr, dmapp, size) 105259014Sroger bktr_ptr_t bktr; 105359014Sroger bus_dmamap_t *dmapp; 105459014Sroger unsigned int size; 105559014Sroger{ 105659014Sroger bus_dma_tag_t dmat = bktr->dmat; 105759014Sroger bus_dma_segment_t seg; 105859014Sroger bus_size_t align; 105959014Sroger int rseg; 106059014Sroger caddr_t kva; 106159014Sroger 106259014Sroger /* 106359014Sroger * Allocate a DMA area 106459014Sroger */ 106559014Sroger align = 1 << 24; 106659014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 106759014Sroger &rseg, BUS_DMA_NOWAIT)) { 106859014Sroger align = PAGE_SIZE; 106959014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 107059014Sroger &rseg, BUS_DMA_NOWAIT)) { 107162112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 107262112Sroger bktr_name(bktr), size); 107359014Sroger return 0; 107459014Sroger } 107559014Sroger } 107659014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 107759014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 107862112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 107962112Sroger bktr_name(bktr), size); 108059014Sroger bus_dmamem_free(dmat, &seg, rseg); 108159014Sroger return 0; 108259014Sroger } 108359014Sroger#ifdef __OpenBSD__ 108459014Sroger bktr->dm_mapsize = size; 108559014Sroger#endif 108659014Sroger /* 108759014Sroger * Create and locd the DMA map for the DMA area 108859014Sroger */ 108959014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 109062112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 109162112Sroger bktr_name(bktr), size); 109259014Sroger bus_dmamem_unmap(dmat, kva, size); 109359014Sroger bus_dmamem_free(dmat, &seg, rseg); 109459014Sroger return 0; 109559014Sroger } 109659014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 109762112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 109862112Sroger bktr_name(bktr), size); 109959014Sroger bus_dmamem_unmap(dmat, kva, size); 110059014Sroger bus_dmamem_free(dmat, &seg, rseg); 110159014Sroger bus_dmamap_destroy(dmat, *dmapp); 110259014Sroger return 0; 110359014Sroger } 110459014Sroger return (vm_offset_t)kva; 110559014Sroger} 110659014Sroger 110759014Srogervoid 110859014Srogerfree_bktr_mem(bktr, dmap, kva) 110959014Sroger bktr_ptr_t bktr; 111059014Sroger bus_dmamap_t dmap; 111159014Sroger vm_offset_t kva; 111259014Sroger{ 111359014Sroger bus_dma_tag_t dmat = bktr->dmat; 111459014Sroger 111559014Sroger#ifdef __NetBSD__ 111659014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 111759014Sroger#else 111859014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 111959014Sroger#endif 112059014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 112159014Sroger bus_dmamap_destroy(dmat, dmap); 112259014Sroger} 112359014Sroger 112459014Sroger 112559014Sroger/*--------------------------------------------------------- 112659014Sroger** 112759014Sroger** BrookTree 848 character device driver routines 112859014Sroger** 112959014Sroger**--------------------------------------------------------- 113059014Sroger*/ 113159014Sroger 113259014Sroger 113359014Sroger#define VIDEO_DEV 0x00 113459014Sroger#define TUNER_DEV 0x01 113559014Sroger#define VBI_DEV 0x02 113659014Sroger 113762112Sroger#define UNIT(x) (minor((x) & 0x0f)) 113862112Sroger#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 113959014Sroger 114059014Sroger/* 114159014Sroger * 114259014Sroger */ 114359014Srogerint 114483366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 114559014Sroger{ 114659014Sroger bktr_ptr_t bktr; 114759014Sroger int unit; 114859014Sroger 114962112Sroger unit = UNIT(dev); 115059014Sroger 115159014Sroger /* unit out of range */ 115259014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 115362112Sroger return(ENXIO); 115459014Sroger 115559014Sroger bktr = bktr_cd.cd_devs[unit]; 115659014Sroger 115759014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 115862112Sroger return(ENXIO); 115959014Sroger 116062112Sroger switch (FUNCTION(dev)) { 116159014Sroger case VIDEO_DEV: 116262112Sroger return(video_open(bktr)); 116359014Sroger case TUNER_DEV: 116462112Sroger return(tuner_open(bktr)); 116559014Sroger case VBI_DEV: 116662112Sroger return(vbi_open(bktr)); 116759014Sroger } 116859014Sroger 116962112Sroger return(ENXIO); 117059014Sroger} 117159014Sroger 117259014Sroger 117359014Sroger/* 117459014Sroger * 117559014Sroger */ 117659014Srogerint 117783366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 117859014Sroger{ 117959014Sroger bktr_ptr_t bktr; 118059014Sroger int unit; 118159014Sroger 118262112Sroger unit = UNIT(dev); 118359014Sroger 118459014Sroger bktr = bktr_cd.cd_devs[unit]; 118559014Sroger 118662112Sroger switch (FUNCTION(dev)) { 118759014Sroger case VIDEO_DEV: 118862112Sroger return(video_close(bktr)); 118959014Sroger case TUNER_DEV: 119062112Sroger return(tuner_close(bktr)); 119159014Sroger case VBI_DEV: 119262112Sroger return(vbi_close(bktr)); 119359014Sroger } 119459014Sroger 119562112Sroger return(ENXIO); 119659014Sroger} 119759014Sroger 119859014Sroger/* 119959014Sroger * 120059014Sroger */ 120159014Srogerint 120262112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 120359014Sroger{ 120459014Sroger bktr_ptr_t bktr; 120559014Sroger int unit; 120659014Sroger 120762112Sroger unit = UNIT(dev); 120859014Sroger 120959014Sroger bktr = bktr_cd.cd_devs[unit]; 121059014Sroger 121162112Sroger switch (FUNCTION(dev)) { 121259014Sroger case VIDEO_DEV: 121362112Sroger return(video_read(bktr, unit, dev, uio)); 121459014Sroger case VBI_DEV: 121562112Sroger return(vbi_read(bktr, uio, ioflag)); 121659014Sroger } 121759014Sroger 121862112Sroger return(ENXIO); 121959014Sroger} 122059014Sroger 122159014Sroger 122259014Sroger/* 122359014Sroger * 122459014Sroger */ 122559014Srogerint 122662112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 122759014Sroger{ 122859014Sroger /* operation not supported */ 122962112Sroger return(EOPNOTSUPP); 123059014Sroger} 123159014Sroger 123259014Sroger/* 123359014Sroger * 123459014Sroger */ 123559014Srogerint 123683366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 123759014Sroger{ 123859014Sroger bktr_ptr_t bktr; 123959014Sroger int unit; 124059014Sroger 124162112Sroger unit = UNIT(dev); 124259014Sroger 124359014Sroger bktr = bktr_cd.cd_devs[unit]; 124459014Sroger 124559014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 124662112Sroger return(ENOMEM); 124759014Sroger 124862112Sroger switch (FUNCTION(dev)) { 124959014Sroger case VIDEO_DEV: 125062112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 125159014Sroger case TUNER_DEV: 125262112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 125359014Sroger } 125459014Sroger 125562112Sroger return(ENXIO); 125659014Sroger} 125759014Sroger 125859014Sroger/* 125959014Sroger * 126059014Sroger */ 126162214Srogerpaddr_t 126262214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 126359014Sroger{ 126459014Sroger int unit; 126559014Sroger bktr_ptr_t bktr; 126659014Sroger 126762112Sroger unit = UNIT(dev); 126859014Sroger 126962112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 127062112Sroger return(-1); 127159014Sroger 127259014Sroger bktr = bktr_cd.cd_devs[unit]; 127359014Sroger 127462112Sroger if ((vaddr_t)offset < 0) 127562112Sroger return(-1); 127659014Sroger 127762112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 127862112Sroger return(-1); 127959014Sroger 128059014Sroger#ifdef __NetBSD__ 128159014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 128262112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 128359014Sroger#else 128462112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 128559014Sroger#endif 128659014Sroger} 128759014Sroger 128851694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1289