bktr_os.c revision 111462
151694Sroger/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 111462 2003-02-25 03:21:22Z mux $ */ 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 = { 25051694Sroger /* open */ bktr_open, 25151694Sroger /* close */ bktr_close, 25251694Sroger /* read */ bktr_read, 25351694Sroger /* write */ bktr_write, 25451694Sroger /* ioctl */ bktr_ioctl, 25551694Sroger /* poll */ bktr_poll, 25651694Sroger /* mmap */ bktr_mmap, 25751694Sroger /* strategy */ nostrategy, 25851694Sroger /* name */ "bktr", 25951694Sroger /* maj */ CDEV_MAJOR, 26051694Sroger /* dump */ nodump, 26151694Sroger /* psize */ nopsize, 26251694Sroger /* flags */ 0, 26351694Sroger}; 26451694Sroger 26552995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 26667306Sroger#if (__FreeBSD_version > 410000) 26765728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 26865728SrogerMODULE_VERSION(bktr, 1); 26967306Sroger#endif 27051694Sroger 27151694Sroger 27251694Sroger/* 27351694Sroger * the boot time probe routine. 27451694Sroger */ 27551694Srogerstatic int 27651694Srogerbktr_probe( device_t dev ) 27751694Sroger{ 27851694Sroger unsigned int type = pci_get_devid(dev); 27951694Sroger unsigned int rev = pci_get_revid(dev); 28051694Sroger 28167306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 28267306Sroger { 28367306Sroger switch (PCI_PRODUCT(type)) { 28467306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 28567306Sroger if (rev == 0x12) 28667306Sroger device_set_desc(dev, "BrookTree 848A"); 28767306Sroger else 28867306Sroger device_set_desc(dev, "BrookTree 848"); 28967306Sroger return 0; 29067306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 29167306Sroger device_set_desc(dev, "BrookTree 849A"); 29267306Sroger return 0; 29367306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 29467306Sroger device_set_desc(dev, "BrookTree 878"); 29567306Sroger return 0; 29667306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 29767306Sroger device_set_desc(dev, "BrookTree 879"); 29867306Sroger return 0; 29967306Sroger } 30051694Sroger }; 30151694Sroger 30251694Sroger return ENXIO; 30351694Sroger} 30451694Sroger 30551694Sroger 30651694Sroger/* 30751694Sroger * the attach routine. 30851694Sroger */ 30951694Srogerstatic int 31051694Srogerbktr_attach( device_t dev ) 31151694Sroger{ 31251694Sroger u_long latency; 31351694Sroger u_long fun; 31451694Sroger u_long val; 31551694Sroger unsigned int rev; 31651694Sroger unsigned int unit; 31751694Sroger int error = 0; 31851694Sroger#ifdef BROOKTREE_IRQ 31951694Sroger u_long old_irq, new_irq; 32051694Sroger#endif 32151694Sroger 32251694Sroger struct bktr_softc *bktr = device_get_softc(dev); 32351694Sroger 32451694Sroger unit = device_get_unit(dev); 32551694Sroger 32662112Sroger /* build the device name for bktr_name() */ 32762112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 32862112Sroger 32951694Sroger /* 33051694Sroger * Enable bus mastering and Memory Mapped device 33151694Sroger */ 33251694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 33351694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 33451694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 33551694Sroger 33651694Sroger /* 33751694Sroger * Map control/status registers. 33851694Sroger */ 33965049Sroger bktr->mem_rid = PCIR_MAPS; 34065049Sroger bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 34165049Sroger 0, ~0, 1, RF_ACTIVE); 34251694Sroger 34365049Sroger 34451694Sroger if (!bktr->res_mem) { 34551694Sroger device_printf(dev, "could not map memory\n"); 34651694Sroger error = ENXIO; 34751694Sroger goto fail; 34851694Sroger } 34959014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 35059014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 35151694Sroger 35259014Sroger 35351694Sroger /* 35451694Sroger * Disable the brooktree device 35551694Sroger */ 35659014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 35759014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 35851694Sroger 35951694Sroger 36051694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 36151694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36251694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 36351694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36451694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 36551694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 36651694Sroger#endif 36751694Sroger 36851694Sroger /* 36951694Sroger * Allocate our interrupt. 37051694Sroger */ 37165049Sroger bktr->irq_rid = 0; 37265049Sroger bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 37365049Sroger 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 37451694Sroger if (bktr->res_irq == NULL) { 37551694Sroger device_printf(dev, "could not map interrupt\n"); 37651694Sroger error = ENXIO; 37751694Sroger goto fail; 37851694Sroger } 37951694Sroger 38059250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 38151694Sroger bktr_intr, bktr, &bktr->res_ih); 38251694Sroger if (error) { 38351694Sroger device_printf(dev, "could not setup irq\n"); 38451694Sroger goto fail; 38551694Sroger 38651694Sroger } 38751694Sroger 38851694Sroger 38951694Sroger /* Update the Device Control Register */ 39051694Sroger /* on Bt878 and Bt879 cards */ 39151694Sroger fun = pci_read_config( dev, 0x40, 2); 39251694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 39351694Sroger 39451694Sroger#if defined( BKTR_430_FX_MODE ) 39551694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 39651694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 39751694Sroger#endif 39851694Sroger 39951694Sroger#if defined( BKTR_SIS_VIA_MODE ) 40051694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 40151694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 40251694Sroger OPTi chipset motherboards too */ 40351694Sroger#endif 40451694Sroger pci_write_config(dev, 0x40, fun, 2); 40551694Sroger 40665692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 40793023Snsouch if (bt848_i2c_attach(dev)) 40851694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 40951694Sroger#endif 41051694Sroger 41151694Sroger/* 41251694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 41351694Sroger * you have more than four, then 16 would probably be a better value. 41451694Sroger */ 41551694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 41651694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 41751694Sroger#endif 41851694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 41951694Sroger latency = (latency >> 8) & 0xff; 42051694Sroger if ( bootverbose ) { 42151694Sroger if (latency) 42251694Sroger printf("brooktree%d: PCI bus latency is", unit); 42351694Sroger else 42451694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 42551694Sroger unit); 42651694Sroger } 42751694Sroger if ( !latency ) { 42851694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 42951694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 43051694Sroger } 43151694Sroger if ( bootverbose ) { 43251694Sroger printf(" %d.\n", (int) latency); 43351694Sroger } 43451694Sroger 43551694Sroger /* read the pci device id and revision id */ 43651694Sroger fun = pci_get_devid(dev); 43751694Sroger rev = pci_get_revid(dev); 43851694Sroger 43951694Sroger /* call the common attach code */ 44051694Sroger common_bktr_attach( bktr, unit, fun, rev ); 44151694Sroger 44267306Sroger /* make the device entries */ 44367306Sroger bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 44467306Sroger 0, 0, 0444, "bktr%d", unit); 44567306Sroger bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 44667306Sroger 0, 0, 0444, "tuner%d", unit); 44767306Sroger bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 44867306Sroger 0, 0, 0444, "vbi%d" , unit); 44951694Sroger 45067306Sroger 45167306Sroger /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 45267306Sroger /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 45367306Sroger#if (__FreeBSD_version >=500000) 45467306Sroger if (unit == 0) { 45567306Sroger bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 45667306Sroger bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 45767306Sroger bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 45867306Sroger } 45967306Sroger#endif 46067306Sroger 46151694Sroger return 0; 46251694Sroger 46351694Srogerfail: 46465049Sroger if (bktr->res_irq) 46565049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 46665049Sroger if (bktr->res_mem) 46765049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 46851694Sroger return error; 46951694Sroger 47051694Sroger} 47151694Sroger 47251694Sroger/* 47351694Sroger * the detach routine. 47451694Sroger */ 47551694Srogerstatic int 47651694Srogerbktr_detach( device_t dev ) 47751694Sroger{ 47867366Sroger unsigned int unit; 47967366Sroger 48051694Sroger struct bktr_softc *bktr = device_get_softc(dev); 48151694Sroger 48267366Sroger unit = device_get_unit(dev); 48367366Sroger 48451694Sroger /* Disable the brooktree device */ 48559014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 48659014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 48751694Sroger 48893023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 48993023Snsouch if (bt848_i2c_detach(dev)) 49093023Snsouch printf("bktr%d: i2c_attach: can't attach\n", unit); 49193023Snsouch#endif 49293023Snsouch 49367306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 49467306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 49567306Sroger /* then reload the main bktr driver module */ 49651694Sroger 497107699Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices, 498107699Sroger * the aliases for unit 0 are automatically destroyed */ 49967306Sroger destroy_dev(bktr->vbidev); 50067306Sroger destroy_dev(bktr->tunerdev); 50167306Sroger destroy_dev(bktr->bktrdev); 50267306Sroger 50351694Sroger /* 50451694Sroger * Deallocate resources. 50551694Sroger */ 50651694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 50765049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 50865049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 50965049Sroger 51051694Sroger return 0; 51151694Sroger} 51251694Sroger 51351694Sroger/* 51451694Sroger * the shutdown routine. 51551694Sroger */ 51651694Srogerstatic int 51751694Srogerbktr_shutdown( device_t dev ) 51851694Sroger{ 51951694Sroger struct bktr_softc *bktr = device_get_softc(dev); 52051694Sroger 52151694Sroger /* Disable the brooktree device */ 52259014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 52359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 52451694Sroger 52551694Sroger return 0; 52651694Sroger} 52751694Sroger 52851694Sroger 52951694Sroger/* 53051694Sroger * Special Memory Allocation 53151694Sroger */ 53251694Srogervm_offset_t 53351694Srogerget_bktr_mem( int unit, unsigned size ) 53451694Sroger{ 53551694Sroger vm_offset_t addr = 0; 53651694Sroger 53751694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 53851694Sroger if (addr == 0) 53951694Sroger addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 54051694Sroger if (addr == 0) { 54151694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 54251694Sroger unit, size); 54351694Sroger } 54451694Sroger 54551694Sroger return( addr ); 54651694Sroger} 54751694Sroger 54851694Sroger 54951694Sroger/*--------------------------------------------------------- 55051694Sroger** 55151694Sroger** BrookTree 848 character device driver routines 55251694Sroger** 55351694Sroger**--------------------------------------------------------- 55451694Sroger*/ 55551694Sroger 55651694Sroger#define VIDEO_DEV 0x00 55751694Sroger#define TUNER_DEV 0x01 55851694Sroger#define VBI_DEV 0x02 55951694Sroger 56051694Sroger#define UNIT(x) ((x) & 0x0f) 56151694Sroger#define FUNCTION(x) (x >> 4) 56251694Sroger 56351694Sroger/* 56451694Sroger * 56551694Sroger */ 566104094Sphkstatic int 56783366Sjulianbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 56851694Sroger{ 56951694Sroger bktr_ptr_t bktr; 57051694Sroger int unit; 57151694Sroger int result; 57251694Sroger 57351694Sroger unit = UNIT( minor(dev) ); 57451694Sroger 57551694Sroger /* Get the device data */ 57651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 57751694Sroger if (bktr == NULL) { 57851694Sroger /* the device is no longer valid/functioning */ 57951694Sroger return (ENXIO); 58051694Sroger } 58151694Sroger 58251694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 58351694Sroger return( ENXIO ); 58451694Sroger 58551694Sroger /* Record that the device is now busy */ 58651694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 58751694Sroger 58851694Sroger 58951694Sroger if (bt848_card != -1) { 59051694Sroger if ((bt848_card >> 8 == unit ) && 59151694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 59251694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 59351694Sroger bktr->bt848_card = (bt848_card & 0xff); 59451694Sroger probeCard(bktr, FALSE, unit); 59551694Sroger } 59651694Sroger } 59751694Sroger } 59851694Sroger 59951694Sroger if (bt848_tuner != -1) { 60051694Sroger if ((bt848_tuner >> 8 == unit ) && 60151694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 60251694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 60351694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 60451694Sroger probeCard(bktr, FALSE, unit); 60551694Sroger } 60651694Sroger } 60751694Sroger } 60851694Sroger 60951694Sroger if (bt848_reverse_mute != -1) { 61059014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 61151694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 61251694Sroger } 61351694Sroger } 61451694Sroger 61559014Sroger if (bt848_slow_msp_audio != -1) { 61659014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 61759014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 61859014Sroger } 61959014Sroger } 62059014Sroger 62151694Sroger switch ( FUNCTION( minor(dev) ) ) { 62251694Sroger case VIDEO_DEV: 62351694Sroger result = video_open( bktr ); 62451694Sroger break; 62551694Sroger case TUNER_DEV: 62651694Sroger result = tuner_open( bktr ); 62751694Sroger break; 62851694Sroger case VBI_DEV: 62951694Sroger result = vbi_open( bktr ); 63051694Sroger break; 63151694Sroger default: 63251694Sroger result = ENXIO; 63351694Sroger break; 63451694Sroger } 63551694Sroger 63651694Sroger /* If there was an error opening the device, undo the busy status */ 63751694Sroger if (result != 0) 63851694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 63951694Sroger return( result ); 64051694Sroger} 64151694Sroger 64251694Sroger 64351694Sroger/* 64451694Sroger * 64551694Sroger */ 646104094Sphkstatic int 64783366Sjulianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 64851694Sroger{ 64951694Sroger bktr_ptr_t bktr; 65051694Sroger int unit; 65151694Sroger int result; 65251694Sroger 65351694Sroger unit = UNIT( minor(dev) ); 65451694Sroger 65551694Sroger /* Get the device data */ 65651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 65751694Sroger if (bktr == NULL) { 65851694Sroger /* the device is no longer valid/functioning */ 65951694Sroger return (ENXIO); 66051694Sroger } 66151694Sroger 66251694Sroger switch ( FUNCTION( minor(dev) ) ) { 66351694Sroger case VIDEO_DEV: 66451694Sroger result = video_close( bktr ); 66551694Sroger break; 66651694Sroger case TUNER_DEV: 66751694Sroger result = tuner_close( bktr ); 66851694Sroger break; 66951694Sroger case VBI_DEV: 67051694Sroger result = vbi_close( bktr ); 67151694Sroger break; 67251694Sroger default: 67351694Sroger return (ENXIO); 67451694Sroger break; 67551694Sroger } 67651694Sroger 67751694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 67851694Sroger return( result ); 67951694Sroger} 68051694Sroger 68151694Sroger 68251694Sroger/* 68351694Sroger * 68451694Sroger */ 685104094Sphkstatic int 68651694Srogerbktr_read( dev_t dev, struct uio *uio, int ioflag ) 68751694Sroger{ 68851694Sroger bktr_ptr_t bktr; 68951694Sroger int unit; 69051694Sroger 69151694Sroger unit = UNIT(minor(dev)); 69251694Sroger 69351694Sroger /* Get the device data */ 69451694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 69551694Sroger if (bktr == NULL) { 69651694Sroger /* the device is no longer valid/functioning */ 69751694Sroger return (ENXIO); 69851694Sroger } 69951694Sroger 70051694Sroger switch ( FUNCTION( minor(dev) ) ) { 70151694Sroger case VIDEO_DEV: 70251694Sroger return( video_read( bktr, unit, dev, uio ) ); 70351694Sroger case VBI_DEV: 70451694Sroger return( vbi_read( bktr, uio, ioflag ) ); 70551694Sroger } 70651694Sroger return( ENXIO ); 70751694Sroger} 70851694Sroger 70951694Sroger 71051694Sroger/* 71151694Sroger * 71251694Sroger */ 713104094Sphkstatic int 71451694Srogerbktr_write( dev_t dev, struct uio *uio, int ioflag ) 71551694Sroger{ 71651694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 71751694Sroger} 71851694Sroger 71951694Sroger 72051694Sroger/* 72151694Sroger * 72251694Sroger */ 723104094Sphkstatic int 72483366Sjulianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 72551694Sroger{ 72651694Sroger bktr_ptr_t bktr; 72751694Sroger int unit; 72851694Sroger 72951694Sroger unit = UNIT(minor(dev)); 73051694Sroger 73151694Sroger /* Get the device data */ 73251694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 73351694Sroger if (bktr == NULL) { 73451694Sroger /* the device is no longer valid/functioning */ 73551694Sroger return (ENXIO); 73651694Sroger } 73751694Sroger 73851694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 73951694Sroger return( ENOMEM ); 74051694Sroger 74151694Sroger switch ( FUNCTION( minor(dev) ) ) { 74251694Sroger case VIDEO_DEV: 74383366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 74451694Sroger case TUNER_DEV: 74583366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 74651694Sroger } 74751694Sroger 74851694Sroger return( ENXIO ); 74951694Sroger} 75051694Sroger 75151694Sroger 75251694Sroger/* 75351694Sroger * 75451694Sroger */ 755104094Sphkstatic int 756111462Smuxbktr_mmap( dev_t dev, vm_offset_t offset, vm_offset_t *paddr, int nprot ) 75751694Sroger{ 75851694Sroger int unit; 75951694Sroger bktr_ptr_t bktr; 76051694Sroger 76151694Sroger unit = UNIT(minor(dev)); 76251694Sroger 76351694Sroger if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 76451694Sroger return( -1 ); 76551694Sroger 76651694Sroger /* Get the device data */ 76751694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76851694Sroger if (bktr == NULL) { 76951694Sroger /* the device is no longer valid/functioning */ 77051694Sroger return (ENXIO); 77151694Sroger } 77251694Sroger 77351694Sroger if (nprot & PROT_EXEC) 77451694Sroger return( -1 ); 77551694Sroger 77651694Sroger if (offset < 0) 77751694Sroger return( -1 ); 77851694Sroger 77951694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 78051694Sroger return( -1 ); 78151694Sroger 782111462Smux *paddr = vtophys(bktr->bigbuf) + offset; 783111462Smux return( 0 ); 78451694Sroger} 78551694Sroger 786104094Sphkstatic int 787104094Sphkbktr_poll( dev_t dev, int events, struct thread *td) 78851694Sroger{ 78951694Sroger int unit; 79051694Sroger bktr_ptr_t bktr; 79151694Sroger int revents = 0; 79259277Sroger DECLARE_INTR_MASK(s); 79351694Sroger 79451694Sroger unit = UNIT(minor(dev)); 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 80359277Sroger DISABLE_INTR(s); 80451694Sroger 80551694Sroger if (events & (POLLIN | POLLRDNORM)) { 80651694Sroger 80751694Sroger switch ( FUNCTION( minor(dev) ) ) { 80851694Sroger case VBI_DEV: 80951694Sroger if(bktr->vbisize == 0) 81083366Sjulian selrecord(td, &bktr->vbi_select); 81151694Sroger else 81251694Sroger revents |= events & (POLLIN | POLLRDNORM); 81351694Sroger break; 81451694Sroger } 81551694Sroger } 81651694Sroger 81759250Sroger ENABLE_INTR(s); 81851694Sroger 81951694Sroger return (revents); 82051694Sroger} 82151694Sroger 82251694Sroger#endif /* FreeBSD 4.x specific kernel interface routines */ 82351694Sroger 82451694Sroger/*****************/ 82551694Sroger/* *** BSDI *** */ 82651694Sroger/*****************/ 82751694Sroger 82851694Sroger#if defined(__bsdi__) 82951694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 83051694Sroger 83151694Sroger 83251694Sroger/*****************************/ 83351694Sroger/* *** OpenBSD / NetBSD *** */ 83451694Sroger/*****************************/ 83551694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 83659014Sroger 83759014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 83859014Sroger 83959014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 84059014Sroger 84159014Sroger#define bktr_open bktropen 84259014Sroger#define bktr_close bktrclose 84359014Sroger#define bktr_read bktrread 84459014Sroger#define bktr_write bktrwrite 84559014Sroger#define bktr_ioctl bktrioctl 84659014Sroger#define bktr_mmap bktrmmap 84759014Sroger 84859014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 84959014Sroger vm_offset_t, vm_offset_t); 85059014Sroger 85162112Sroger#if defined(__OpenBSD__) 85292739Salfredstatic int bktr_probe(struct device *, void *, void *); 85359014Sroger#else 85492739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 85559014Sroger#endif 85692739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 85759014Sroger 85859014Srogerstruct cfattach bktr_ca = { 85959014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 86059014Sroger}; 86159014Sroger 86259014Sroger#if defined(__NetBSD__) 86359014Srogerextern struct cfdriver bktr_cd; 86459014Sroger#else 86559014Srogerstruct cfdriver bktr_cd = { 86659014Sroger NULL, "bktr", DV_DULL 86759014Sroger}; 86859014Sroger#endif 86959014Sroger 87062112Srogerint 87162112Srogerbktr_probe(parent, match, aux) 87262112Sroger struct device *parent; 87362112Sroger#if defined(__OpenBSD__) 87459014Sroger void *match; 87559014Sroger#else 87659014Sroger struct cfdata *match; 87759014Sroger#endif 87859014Sroger void *aux; 87959014Sroger{ 88059014Sroger struct pci_attach_args *pa = aux; 88159014Sroger 88259014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 88359014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 88459014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 88559014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 88659014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 88759014Sroger return 1; 88859014Sroger 88959014Sroger return 0; 89059014Sroger} 89159014Sroger 89259014Sroger 89359014Sroger/* 89459014Sroger * the attach routine. 89559014Sroger */ 89659014Srogerstatic void 89762112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 89859014Sroger{ 89959014Sroger bktr_ptr_t bktr; 90059014Sroger u_long latency; 90159014Sroger u_long fun; 90259014Sroger unsigned int rev; 90359014Sroger 90459014Sroger#if defined(__OpenBSD__) 90559014Sroger struct pci_attach_args *pa = aux; 90659014Sroger pci_chipset_tag_t pc = pa->pa_pc; 90759014Sroger 90859014Sroger pci_intr_handle_t ih; 90959014Sroger const char *intrstr; 91059014Sroger int retval; 91159014Sroger int unit; 91259014Sroger 91359014Sroger bktr = (bktr_ptr_t)self; 91459014Sroger unit = bktr->bktr_dev.dv_unit; 91559014Sroger 91659014Sroger bktr->pc = pa->pa_pc; 91759014Sroger bktr->tag = pa->pa_tag; 91859014Sroger bktr->dmat = pa->pa_dmat; 91959014Sroger 92059014Sroger /* 92159014Sroger * map memory 92259014Sroger */ 92359014Sroger bktr->memt = pa->pa_memt; 92459014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 92559014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 92659014Sroger if (!retval) 92759014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 92859014Sroger bktr->obmemsz, 0, &bktr->memh); 92959014Sroger if (retval) { 93059014Sroger printf(": couldn't map memory\n"); 93159014Sroger return; 93259014Sroger } 93359014Sroger 93459014Sroger 93559014Sroger /* 93659014Sroger * map interrupt 93759014Sroger */ 93859014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 93959014Sroger pa->pa_intrline, &ih)) { 94059014Sroger printf(": couldn't map interrupt\n"); 94159014Sroger return; 94259014Sroger } 94359014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 94459014Sroger 94559014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 94659014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 94759014Sroger if (bktr->ih == NULL) { 94859014Sroger printf(": couldn't establish interrupt"); 94959014Sroger if (intrstr != NULL) 95059014Sroger printf(" at %s", intrstr); 95159014Sroger printf("\n"); 95259014Sroger return; 95359014Sroger } 95459014Sroger 95559014Sroger if (intrstr != NULL) 95659014Sroger printf(": %s\n", intrstr); 95759014Sroger#endif /* __OpenBSD__ */ 95859014Sroger 95959014Sroger#if defined(__NetBSD__) 96059014Sroger struct pci_attach_args *pa = aux; 96159014Sroger pci_intr_handle_t ih; 96259014Sroger const char *intrstr; 96359014Sroger int retval; 96459014Sroger int unit; 96559014Sroger 96659014Sroger bktr = (bktr_ptr_t)self; 96759014Sroger unit = bktr->bktr_dev.dv_unit; 96859014Sroger bktr->dmat = pa->pa_dmat; 96959014Sroger 97059014Sroger printf("\n"); 97159014Sroger 97259014Sroger /* 97359014Sroger * map memory 97459014Sroger */ 97559014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 97662112Sroger PCI_MAPREG_TYPE_MEM 97762112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 97862112Sroger &bktr->memt, &bktr->memh, NULL, 97962112Sroger &bktr->obmemsz); 98062112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 98162112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 98259014Sroger if (retval) { 98362112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 98459014Sroger return; 98559014Sroger } 98659014Sroger 98759014Sroger /* 98859014Sroger * Disable the brooktree device 98959014Sroger */ 99059014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 99159014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 99259014Sroger 99359014Sroger /* 99459014Sroger * map interrupt 99559014Sroger */ 99659014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 99759014Sroger pa->pa_intrline, &ih)) { 99862112Sroger printf("%s: couldn't map interrupt\n", 99962112Sroger bktr_name(bktr)); 100059014Sroger return; 100159014Sroger } 100259014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 100359014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 100459014Sroger bktr_intr, bktr); 100559014Sroger if (bktr->ih == NULL) { 100659014Sroger printf("%s: couldn't establish interrupt", 100762112Sroger bktr_name(bktr)); 100862112Sroger if (intrstr != NULL) 100962112Sroger printf(" at %s", intrstr); 101062112Sroger printf("\n"); 101162112Sroger return; 101259014Sroger } 101359014Sroger if (intrstr != NULL) 101462112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 101559014Sroger intrstr); 101659014Sroger#endif /* __NetBSD__ */ 101759014Sroger 101859014Sroger/* 101959014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 102059014Sroger * you have more than four, then 16 would probably be a better value. 102159014Sroger */ 102259014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 102359014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 102459014Sroger#endif 102559014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 102659014Sroger latency = (latency >> 8) & 0xff; 102759014Sroger 102862112Sroger if (!latency) { 102962112Sroger if (bootverbose) { 103059014Sroger printf("%s: PCI bus latency was 0 changing to %d", 103162112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 103259014Sroger } 103359014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 103459014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 103559014Sroger PCI_LATENCY_TIMER, latency<<8); 103659014Sroger } 103759014Sroger 103859014Sroger 103962112Sroger /* Enabled Bus Master 104062112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 104162112Sroger boot) */ 104259014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 104362112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 104462112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 104559014Sroger 104659014Sroger /* read the pci id and determine the card type */ 104759014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 104859014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 104959014Sroger 105062112Sroger common_bktr_attach(bktr, unit, fun, rev); 105159014Sroger} 105259014Sroger 105359014Sroger 105459014Sroger/* 105559014Sroger * Special Memory Allocation 105659014Sroger */ 105759014Srogervm_offset_t 105859014Srogerget_bktr_mem(bktr, dmapp, size) 105959014Sroger bktr_ptr_t bktr; 106059014Sroger bus_dmamap_t *dmapp; 106159014Sroger unsigned int size; 106259014Sroger{ 106359014Sroger bus_dma_tag_t dmat = bktr->dmat; 106459014Sroger bus_dma_segment_t seg; 106559014Sroger bus_size_t align; 106659014Sroger int rseg; 106759014Sroger caddr_t kva; 106859014Sroger 106959014Sroger /* 107059014Sroger * Allocate a DMA area 107159014Sroger */ 107259014Sroger align = 1 << 24; 107359014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 107459014Sroger &rseg, BUS_DMA_NOWAIT)) { 107559014Sroger align = PAGE_SIZE; 107659014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 107759014Sroger &rseg, BUS_DMA_NOWAIT)) { 107862112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 107962112Sroger bktr_name(bktr), size); 108059014Sroger return 0; 108159014Sroger } 108259014Sroger } 108359014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 108459014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 108562112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 108662112Sroger bktr_name(bktr), size); 108759014Sroger bus_dmamem_free(dmat, &seg, rseg); 108859014Sroger return 0; 108959014Sroger } 109059014Sroger#ifdef __OpenBSD__ 109159014Sroger bktr->dm_mapsize = size; 109259014Sroger#endif 109359014Sroger /* 109459014Sroger * Create and locd the DMA map for the DMA area 109559014Sroger */ 109659014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 109762112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 109862112Sroger bktr_name(bktr), size); 109959014Sroger bus_dmamem_unmap(dmat, kva, size); 110059014Sroger bus_dmamem_free(dmat, &seg, rseg); 110159014Sroger return 0; 110259014Sroger } 110359014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 110462112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 110562112Sroger bktr_name(bktr), size); 110659014Sroger bus_dmamem_unmap(dmat, kva, size); 110759014Sroger bus_dmamem_free(dmat, &seg, rseg); 110859014Sroger bus_dmamap_destroy(dmat, *dmapp); 110959014Sroger return 0; 111059014Sroger } 111159014Sroger return (vm_offset_t)kva; 111259014Sroger} 111359014Sroger 111459014Srogervoid 111559014Srogerfree_bktr_mem(bktr, dmap, kva) 111659014Sroger bktr_ptr_t bktr; 111759014Sroger bus_dmamap_t dmap; 111859014Sroger vm_offset_t kva; 111959014Sroger{ 112059014Sroger bus_dma_tag_t dmat = bktr->dmat; 112159014Sroger 112259014Sroger#ifdef __NetBSD__ 112359014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 112459014Sroger#else 112559014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 112659014Sroger#endif 112759014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 112859014Sroger bus_dmamap_destroy(dmat, dmap); 112959014Sroger} 113059014Sroger 113159014Sroger 113259014Sroger/*--------------------------------------------------------- 113359014Sroger** 113459014Sroger** BrookTree 848 character device driver routines 113559014Sroger** 113659014Sroger**--------------------------------------------------------- 113759014Sroger*/ 113859014Sroger 113959014Sroger 114059014Sroger#define VIDEO_DEV 0x00 114159014Sroger#define TUNER_DEV 0x01 114259014Sroger#define VBI_DEV 0x02 114359014Sroger 114462112Sroger#define UNIT(x) (minor((x) & 0x0f)) 114562112Sroger#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 114659014Sroger 114759014Sroger/* 114859014Sroger * 114959014Sroger */ 115059014Srogerint 115183366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 115259014Sroger{ 115359014Sroger bktr_ptr_t bktr; 115459014Sroger int unit; 115559014Sroger 115662112Sroger unit = UNIT(dev); 115759014Sroger 115859014Sroger /* unit out of range */ 115959014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 116062112Sroger return(ENXIO); 116159014Sroger 116259014Sroger bktr = bktr_cd.cd_devs[unit]; 116359014Sroger 116459014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 116562112Sroger return(ENXIO); 116659014Sroger 116762112Sroger switch (FUNCTION(dev)) { 116859014Sroger case VIDEO_DEV: 116962112Sroger return(video_open(bktr)); 117059014Sroger case TUNER_DEV: 117162112Sroger return(tuner_open(bktr)); 117259014Sroger case VBI_DEV: 117362112Sroger return(vbi_open(bktr)); 117459014Sroger } 117559014Sroger 117662112Sroger return(ENXIO); 117759014Sroger} 117859014Sroger 117959014Sroger 118059014Sroger/* 118159014Sroger * 118259014Sroger */ 118359014Srogerint 118483366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 118559014Sroger{ 118659014Sroger bktr_ptr_t bktr; 118759014Sroger int unit; 118859014Sroger 118962112Sroger unit = UNIT(dev); 119059014Sroger 119159014Sroger bktr = bktr_cd.cd_devs[unit]; 119259014Sroger 119362112Sroger switch (FUNCTION(dev)) { 119459014Sroger case VIDEO_DEV: 119562112Sroger return(video_close(bktr)); 119659014Sroger case TUNER_DEV: 119762112Sroger return(tuner_close(bktr)); 119859014Sroger case VBI_DEV: 119962112Sroger return(vbi_close(bktr)); 120059014Sroger } 120159014Sroger 120262112Sroger return(ENXIO); 120359014Sroger} 120459014Sroger 120559014Sroger/* 120659014Sroger * 120759014Sroger */ 120859014Srogerint 120962112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 121059014Sroger{ 121159014Sroger bktr_ptr_t bktr; 121259014Sroger int unit; 121359014Sroger 121462112Sroger unit = UNIT(dev); 121559014Sroger 121659014Sroger bktr = bktr_cd.cd_devs[unit]; 121759014Sroger 121862112Sroger switch (FUNCTION(dev)) { 121959014Sroger case VIDEO_DEV: 122062112Sroger return(video_read(bktr, unit, dev, uio)); 122159014Sroger case VBI_DEV: 122262112Sroger return(vbi_read(bktr, uio, ioflag)); 122359014Sroger } 122459014Sroger 122562112Sroger return(ENXIO); 122659014Sroger} 122759014Sroger 122859014Sroger 122959014Sroger/* 123059014Sroger * 123159014Sroger */ 123259014Srogerint 123362112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 123459014Sroger{ 123559014Sroger /* operation not supported */ 123662112Sroger return(EOPNOTSUPP); 123759014Sroger} 123859014Sroger 123959014Sroger/* 124059014Sroger * 124159014Sroger */ 124259014Srogerint 124383366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 124459014Sroger{ 124559014Sroger bktr_ptr_t bktr; 124659014Sroger int unit; 124759014Sroger 124862112Sroger unit = UNIT(dev); 124959014Sroger 125059014Sroger bktr = bktr_cd.cd_devs[unit]; 125159014Sroger 125259014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 125362112Sroger return(ENOMEM); 125459014Sroger 125562112Sroger switch (FUNCTION(dev)) { 125659014Sroger case VIDEO_DEV: 125762112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 125859014Sroger case TUNER_DEV: 125962112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 126059014Sroger } 126159014Sroger 126262112Sroger return(ENXIO); 126359014Sroger} 126459014Sroger 126559014Sroger/* 126659014Sroger * 126759014Sroger */ 126862214Srogerpaddr_t 126962214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 127059014Sroger{ 127159014Sroger int unit; 127259014Sroger bktr_ptr_t bktr; 127359014Sroger 127462112Sroger unit = UNIT(dev); 127559014Sroger 127662112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 127762112Sroger return(-1); 127859014Sroger 127959014Sroger bktr = bktr_cd.cd_devs[unit]; 128059014Sroger 128162112Sroger if ((vaddr_t)offset < 0) 128262112Sroger return(-1); 128359014Sroger 128462112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 128562112Sroger return(-1); 128659014Sroger 128759014Sroger#ifdef __NetBSD__ 128859014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 128962112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 129059014Sroger#else 129162112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 129259014Sroger#endif 129359014Sroger} 129459014Sroger 129551694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1296