bktr_os.c revision 192805
1119418Sobrien/*- 251694Sroger * 1. Redistributions of source code must retain the 351694Sroger * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 451694Sroger * All rights reserved. 551694Sroger * 651694Sroger * Redistribution and use in source and binary forms, with or without 751694Sroger * modification, are permitted provided that the following conditions 851694Sroger * are met: 951694Sroger * 1. Redistributions of source code must retain the above copyright 1051694Sroger * notice, this list of conditions and the following disclaimer. 1151694Sroger * 2. Redistributions in binary form must reproduce the above copyright 1251694Sroger * notice, this list of conditions and the following disclaimer in the 1351694Sroger * documentation and/or other materials provided with the distribution. 1451694Sroger * 3. All advertising materials mentioning features or use of this software 1551694Sroger * must display the following acknowledgement: 1651694Sroger * This product includes software developed by Amancio Hasty and 1751694Sroger * Roger Hardiman 1851694Sroger * 4. The name of the author may not be used to endorse or promote products 1951694Sroger * derived from this software without specific prior written permission. 2051694Sroger * 2151694Sroger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2251694Sroger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2351694Sroger * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2451694Sroger * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2551694Sroger * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2651694Sroger * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2751694Sroger * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2851694Sroger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2951694Sroger * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3051694Sroger * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3151694Sroger * POSSIBILITY OF SUCH DAMAGE. 3251694Sroger */ 3351694Sroger 34119418Sobrien#include <sys/cdefs.h> 35119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_os.c 192805 2009-05-26 12:01:37Z ed $"); 3651694Sroger 37119418Sobrien/* 38119418Sobrien * This is part of the Driver for Video Capture Cards (Frame grabbers) 39119418Sobrien * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 40119418Sobrien * chipset. 41119418Sobrien * Copyright Roger Hardiman and Amancio Hasty. 42119418Sobrien * 43119418Sobrien * bktr_os : This has all the Operating System dependant code, 44119418Sobrien * probe/attach and open/close/ioctl/read/mmap 45119418Sobrien * memory allocation 46119418Sobrien * PCI bus interfacing 47119418Sobrien */ 48119418Sobrien 4959014Sroger#include "opt_bktr.h" /* include any kernel config options */ 5051694Sroger 5151694Sroger#define FIFO_RISC_DISABLED 0 5251694Sroger#define ALL_INTS_DISABLED 0 5351694Sroger 5462214Sroger 5562214Sroger/*******************/ 5662214Sroger/* *** FreeBSD *** */ 5762214Sroger/*******************/ 5862214Sroger#ifdef __FreeBSD__ 5962214Sroger 6051694Sroger#include <sys/param.h> 6151694Sroger#include <sys/systm.h> 6251694Sroger#include <sys/conf.h> 6351694Sroger#include <sys/uio.h> 6451694Sroger#include <sys/kernel.h> 65129879Sphk#include <sys/module.h> 6651694Sroger#include <sys/signalvar.h> 67124507Salc#include <sys/malloc.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 7651694Sroger#include <vm/vm.h> 7751694Sroger#include <vm/vm_kern.h> 7851694Sroger#include <vm/pmap.h> 7951694Sroger#include <vm/vm_extern.h> 8051694Sroger 8151694Sroger#include <sys/bus.h> /* used by smbus and newbus */ 8251694Sroger 8359014Sroger#include <machine/bus.h> /* used by bus space and newbus */ 8459014Sroger#include <sys/bus.h> 8559014Sroger 8651694Sroger#include <sys/rman.h> /* used by newbus */ 8751694Sroger#include <machine/resource.h> /* used by newbus */ 8851694Sroger 8967306Sroger#if (__FreeBSD_version < 500000) 9067306Sroger#include <machine/clock.h> /* for DELAY */ 9151694Sroger#include <pci/pcivar.h> 9251694Sroger#include <pci/pcireg.h> 93119277Simp#else 94119277Simp#include <dev/pci/pcivar.h> 95119277Simp#include <dev/pci/pcireg.h> 96119277Simp#endif 9751694Sroger 9851694Sroger#include <sys/sysctl.h> 9951694Srogerint bt848_card = -1; 10051694Srogerint bt848_tuner = -1; 10151694Srogerint bt848_reverse_mute = -1; 10251694Srogerint bt848_format = -1; 10359014Srogerint bt848_slow_msp_audio = -1; 104118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 105118819Salexint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 106118819Salexint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 107118819Salex the autoscan seems work well only with FM... */ 108118819Salexint bt848_dolby = 0; 109118819Salex#endif 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, ""); 117118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 118118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 119118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 120118819SalexSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 121118819Salex#endif 12251694Sroger 12362214Sroger#endif /* end freebsd section */ 12451694Sroger 12562214Sroger 12662214Sroger 12751694Sroger/****************/ 12851694Sroger/* *** BSDI *** */ 12951694Sroger/****************/ 13051694Sroger#ifdef __bsdi__ 13151694Sroger#endif /* __bsdi__ */ 13251694Sroger 13351694Sroger 13451694Sroger/**************************/ 13551694Sroger/* *** OpenBSD/NetBSD *** */ 13651694Sroger/**************************/ 13751694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 13862214Sroger 13962214Sroger#include <sys/param.h> 14062214Sroger#include <sys/systm.h> 14162214Sroger#include <sys/conf.h> 14262214Sroger#include <sys/uio.h> 14362214Sroger#include <sys/kernel.h> 14462214Sroger#include <sys/signalvar.h> 14562214Sroger#include <sys/mman.h> 14662214Sroger#include <sys/poll.h> 14762214Sroger#include <sys/select.h> 14862214Sroger#include <sys/vnode.h> 14962214Sroger 15062214Sroger#include <vm/vm.h> 15162214Sroger 152158937Sjmg#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 153158937Sjmg 15462214Sroger#ifndef __NetBSD__ 15562214Sroger#include <vm/vm_kern.h> 15662214Sroger#include <vm/pmap.h> 15762214Sroger#include <vm/vm_extern.h> 15862214Sroger#endif 15962214Sroger 16059014Sroger#include <sys/device.h> 16159014Sroger#include <dev/pci/pcivar.h> 16259014Sroger#include <dev/pci/pcireg.h> 16359014Sroger#include <dev/pci/pcidevs.h> 16459014Sroger 16559014Sroger#define BKTR_DEBUG 16659014Sroger#ifdef BKTR_DEBUG 16759014Srogerint bktr_debug = 0; 16859014Sroger#define DPR(x) (bktr_debug ? printf x : 0) 16959014Sroger#else 17059014Sroger#define DPR(x) 17159014Sroger#endif 17251694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 17351694Sroger 17451694Sroger 17562214Sroger#ifdef __NetBSD__ 17662214Sroger#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 17762214Sroger#include <dev/pci/bktr/bktr_reg.h> 17862214Sroger#include <dev/pci/bktr/bktr_tuner.h> 17962214Sroger#include <dev/pci/bktr/bktr_card.h> 18062214Sroger#include <dev/pci/bktr/bktr_audio.h> 18162214Sroger#include <dev/pci/bktr/bktr_core.h> 18262214Sroger#include <dev/pci/bktr/bktr_os.h> 18362214Sroger#else /* Traditional location for .h files */ 184123291Sobrien#include <dev/bktr/ioctl_meteor.h> 185123291Sobrien#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 18662214Sroger#include <dev/bktr/bktr_reg.h> 18762214Sroger#include <dev/bktr/bktr_tuner.h> 18862214Sroger#include <dev/bktr/bktr_card.h> 18962214Sroger#include <dev/bktr/bktr_audio.h> 19062214Sroger#include <dev/bktr/bktr_core.h> 19162214Sroger#include <dev/bktr/bktr_os.h> 19293023Snsouch 19365692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 19465392Speter#include <dev/bktr/bktr_i2c.h> 19593023Snsouch 19693023Snsouch#include "iicbb_if.h" 19793023Snsouch#include "smbus_if.h" 19862214Sroger#endif 19965392Speter#endif 20051694Sroger 20162214Sroger 20251694Sroger/****************************/ 20351694Sroger/* *** FreeBSD 4.x code *** */ 20451694Sroger/****************************/ 20551694Sroger 20651694Srogerstatic int bktr_probe( device_t dev ); 20751694Srogerstatic int bktr_attach( device_t dev ); 20851694Srogerstatic int bktr_detach( device_t dev ); 20951694Srogerstatic int bktr_shutdown( device_t dev ); 21051694Srogerstatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21151694Sroger 21251694Srogerstatic device_method_t bktr_methods[] = { 21351694Sroger /* Device interface */ 21451694Sroger DEVMETHOD(device_probe, bktr_probe), 21551694Sroger DEVMETHOD(device_attach, bktr_attach), 21651694Sroger DEVMETHOD(device_detach, bktr_detach), 21751694Sroger DEVMETHOD(device_shutdown, bktr_shutdown), 21851694Sroger 21993023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 22093023Snsouch /* iicbb interface */ 22193023Snsouch DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22293023Snsouch DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 22393023Snsouch DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 22493023Snsouch DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 22593023Snsouch DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 22693023Snsouch DEVMETHOD(iicbb_reset, bti2c_iic_reset), 22793023Snsouch 22893023Snsouch /* smbus interface */ 22993023Snsouch DEVMETHOD(smbus_callback, bti2c_smb_callback), 23093023Snsouch DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 23193023Snsouch DEVMETHOD(smbus_writew, bti2c_smb_writew), 23293023Snsouch DEVMETHOD(smbus_readb, bti2c_smb_readb), 23393023Snsouch#endif 23493023Snsouch 23551694Sroger { 0, 0 } 23651694Sroger}; 23751694Sroger 23851694Srogerstatic driver_t bktr_driver = { 23951694Sroger "bktr", 24051694Sroger bktr_methods, 24151694Sroger sizeof(struct bktr_softc), 24251694Sroger}; 24351694Sroger 24451694Srogerstatic devclass_t bktr_devclass; 24551694Sroger 24651694Srogerstatic d_open_t bktr_open; 24751694Srogerstatic d_close_t bktr_close; 24851694Srogerstatic d_read_t bktr_read; 24951694Srogerstatic d_write_t bktr_write; 25051694Srogerstatic d_ioctl_t bktr_ioctl; 25151694Srogerstatic d_mmap_t bktr_mmap; 25251694Srogerstatic d_poll_t bktr_poll; 25351694Sroger 25451694Srogerstatic struct cdevsw bktr_cdevsw = { 255126080Sphk .d_version = D_VERSION, 256126080Sphk .d_flags = D_NEEDGIANT, 257111815Sphk .d_open = bktr_open, 258111815Sphk .d_close = bktr_close, 259111815Sphk .d_read = bktr_read, 260111815Sphk .d_write = bktr_write, 261111815Sphk .d_ioctl = bktr_ioctl, 262111815Sphk .d_poll = bktr_poll, 263111815Sphk .d_mmap = bktr_mmap, 264111815Sphk .d_name = "bktr", 26551694Sroger}; 26651694Sroger 267154897Sjmg#ifdef BKTR_USE_FREEBSD_SMBUS 268154897Sjmg#include <dev/iicbus/iiconf.h> 269154897Sjmg#include <dev/smbus/smbconf.h> 270154897SjmgMODULE_DEPEND(bktr, iicbb, IICBB_MINVER, IICBB_MODVER, IICBB_MAXVER); 271154897SjmgMODULE_DEPEND(bktr, iicbus, IICBUS_MINVER, IICBUS_MODVER, IICBUS_MAXVER); 272154897SjmgMODULE_DEPEND(bktr, smbus, SMBUS_MINVER, SMBUS_MODVER, SMBUS_MAXVER); 273154897Sjmg#endif 27452995SpeterDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 27565728SrogerMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27665728SrogerMODULE_VERSION(bktr, 1); 27751694Sroger 27851694Sroger 27951694Sroger/* 28051694Sroger * the boot time probe routine. 28151694Sroger */ 28251694Srogerstatic int 28351694Srogerbktr_probe( device_t dev ) 28451694Sroger{ 28551694Sroger unsigned int type = pci_get_devid(dev); 28651694Sroger unsigned int rev = pci_get_revid(dev); 28751694Sroger 28867306Sroger if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 28967306Sroger { 29067306Sroger switch (PCI_PRODUCT(type)) { 29167306Sroger case PCI_PRODUCT_BROOKTREE_BT848: 29267306Sroger if (rev == 0x12) 29367306Sroger device_set_desc(dev, "BrookTree 848A"); 29467306Sroger else 29567306Sroger device_set_desc(dev, "BrookTree 848"); 296143163Simp return BUS_PROBE_DEFAULT; 29767306Sroger case PCI_PRODUCT_BROOKTREE_BT849: 29867306Sroger device_set_desc(dev, "BrookTree 849A"); 299143163Simp return BUS_PROBE_DEFAULT; 30067306Sroger case PCI_PRODUCT_BROOKTREE_BT878: 30167306Sroger device_set_desc(dev, "BrookTree 878"); 302143163Simp return BUS_PROBE_DEFAULT; 30367306Sroger case PCI_PRODUCT_BROOKTREE_BT879: 30467306Sroger device_set_desc(dev, "BrookTree 879"); 305143163Simp return BUS_PROBE_DEFAULT; 30667306Sroger } 30751694Sroger }; 30851694Sroger 30951694Sroger return ENXIO; 31051694Sroger} 31151694Sroger 31251694Sroger 31351694Sroger/* 31451694Sroger * the attach routine. 31551694Sroger */ 31651694Srogerstatic int 31751694Srogerbktr_attach( device_t dev ) 31851694Sroger{ 31951694Sroger u_long latency; 32051694Sroger u_long fun; 32151694Sroger u_long val; 32251694Sroger unsigned int rev; 32351694Sroger unsigned int unit; 32451694Sroger int error = 0; 32551694Sroger#ifdef BROOKTREE_IRQ 32651694Sroger u_long old_irq, new_irq; 32751694Sroger#endif 32851694Sroger 32951694Sroger struct bktr_softc *bktr = device_get_softc(dev); 33051694Sroger 33151694Sroger unit = device_get_unit(dev); 33251694Sroger 33362112Sroger /* build the device name for bktr_name() */ 33462112Sroger snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 33562112Sroger 33651694Sroger /* 33751694Sroger * Enable bus mastering and Memory Mapped device 33851694Sroger */ 33951694Sroger val = pci_read_config(dev, PCIR_COMMAND, 4); 34051694Sroger val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 34151694Sroger pci_write_config(dev, PCIR_COMMAND, val, 4); 34251694Sroger 34351694Sroger /* 34451694Sroger * Map control/status registers. 34551694Sroger */ 346119690Sjhb bktr->mem_rid = PCIR_BAR(0); 347127135Snjl bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 348127135Snjl &bktr->mem_rid, RF_ACTIVE); 34951694Sroger 35051694Sroger if (!bktr->res_mem) { 35151694Sroger device_printf(dev, "could not map memory\n"); 35251694Sroger error = ENXIO; 35351694Sroger goto fail; 35451694Sroger } 35559014Sroger bktr->memt = rman_get_bustag(bktr->res_mem); 35659014Sroger bktr->memh = rman_get_bushandle(bktr->res_mem); 35751694Sroger 35859014Sroger 35951694Sroger /* 36051694Sroger * Disable the brooktree device 36151694Sroger */ 36259014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 36359014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 36451694Sroger 36551694Sroger 36651694Sroger#ifdef BROOKTREE_IRQ /* from the configuration file */ 36751694Sroger old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36851694Sroger pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 36951694Sroger new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 37051694Sroger printf("bktr%d: attach: irq changed from %d to %d\n", 37151694Sroger unit, (old_irq & 0xff), (new_irq & 0xff)); 37251694Sroger#endif 37351694Sroger 37451694Sroger /* 37551694Sroger * Allocate our interrupt. 37651694Sroger */ 37765049Sroger bktr->irq_rid = 0; 378127135Snjl bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 379127135Snjl &bktr->irq_rid, RF_SHAREABLE | RF_ACTIVE); 38051694Sroger if (bktr->res_irq == NULL) { 38151694Sroger device_printf(dev, "could not map interrupt\n"); 38251694Sroger error = ENXIO; 38351694Sroger goto fail; 38451694Sroger } 38551694Sroger 38659250Sroger error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 387166901Spiso NULL, bktr_intr, bktr, &bktr->res_ih); 38851694Sroger if (error) { 38951694Sroger device_printf(dev, "could not setup irq\n"); 39051694Sroger goto fail; 39151694Sroger 39251694Sroger } 39351694Sroger 39451694Sroger 39551694Sroger /* Update the Device Control Register */ 39651694Sroger /* on Bt878 and Bt879 cards */ 39751694Sroger fun = pci_read_config( dev, 0x40, 2); 39851694Sroger fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 39951694Sroger 40051694Sroger#if defined( BKTR_430_FX_MODE ) 40151694Sroger if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 40251694Sroger fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 40351694Sroger#endif 40451694Sroger 40551694Sroger#if defined( BKTR_SIS_VIA_MODE ) 40651694Sroger if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 40751694Sroger fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 40851694Sroger OPTi chipset motherboards too */ 40951694Sroger#endif 41051694Sroger pci_write_config(dev, 0x40, fun, 2); 41151694Sroger 41265692Sroger#if defined(BKTR_USE_FREEBSD_SMBUS) 41393023Snsouch if (bt848_i2c_attach(dev)) 41451694Sroger printf("bktr%d: i2c_attach: can't attach\n", unit); 41551694Sroger#endif 41651694Sroger 41751694Sroger/* 41851694Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 41951694Sroger * you have more than four, then 16 would probably be a better value. 42051694Sroger */ 42151694Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 42251694Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 42351694Sroger#endif 42451694Sroger latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 42551694Sroger latency = (latency >> 8) & 0xff; 42651694Sroger if ( bootverbose ) { 42751694Sroger if (latency) 42851694Sroger printf("brooktree%d: PCI bus latency is", unit); 42951694Sroger else 43051694Sroger printf("brooktree%d: PCI bus latency was 0 changing to", 43151694Sroger unit); 43251694Sroger } 43351694Sroger if ( !latency ) { 43451694Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 43551694Sroger pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 43651694Sroger } 43751694Sroger if ( bootverbose ) { 43851694Sroger printf(" %d.\n", (int) latency); 43951694Sroger } 44051694Sroger 44151694Sroger /* read the pci device id and revision id */ 44251694Sroger fun = pci_get_devid(dev); 44351694Sroger rev = pci_get_revid(dev); 44451694Sroger 44551694Sroger /* call the common attach code */ 44651694Sroger common_bktr_attach( bktr, unit, fun, rev ); 44751694Sroger 44867306Sroger /* make the device entries */ 44967306Sroger bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 45067306Sroger 0, 0, 0444, "bktr%d", unit); 45167306Sroger bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 45267306Sroger 0, 0, 0444, "tuner%d", unit); 45367306Sroger bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 45467306Sroger 0, 0, 0444, "vbi%d" , unit); 45551694Sroger 45667306Sroger 45767306Sroger /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 45867306Sroger /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 45967306Sroger#if (__FreeBSD_version >=500000) 46067306Sroger if (unit == 0) { 46167306Sroger bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 46267306Sroger bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 46367306Sroger bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 46467306Sroger } 46567306Sroger#endif 46667306Sroger 46751694Sroger return 0; 46851694Sroger 46951694Srogerfail: 47065049Sroger if (bktr->res_irq) 47165049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 47265049Sroger if (bktr->res_mem) 473192805Sed bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 47451694Sroger return error; 47551694Sroger 47651694Sroger} 47751694Sroger 47851694Sroger/* 47951694Sroger * the detach routine. 48051694Sroger */ 48151694Srogerstatic int 48251694Srogerbktr_detach( device_t dev ) 48351694Sroger{ 48451694Sroger struct bktr_softc *bktr = device_get_softc(dev); 48551694Sroger 486118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 487118819Salex /* Disable the soundchip and kernel thread */ 488118819Salex if (bktr->msp3400c_info != NULL) 489118819Salex msp_detach(bktr); 490118819Salex#endif 491118819Salex 49251694Sroger /* Disable the brooktree device */ 49359014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 49459014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49551694Sroger 49693023Snsouch#if defined(BKTR_USE_FREEBSD_SMBUS) 49793023Snsouch if (bt848_i2c_detach(dev)) 498115556Sphk printf("bktr%d: i2c_attach: can't attach\n", 499115556Sphk device_get_unit(dev)); 50093023Snsouch#endif 501123088Struckman#ifdef USE_VBIMUTEX 502123088Struckman mtx_destroy(&bktr->vbimutex); 503123088Struckman#endif 50493023Snsouch 50567306Sroger /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50667306Sroger /* The memory is retained by the bktr_mem module so we can unload and */ 50767306Sroger /* then reload the main bktr driver module */ 50851694Sroger 509107699Sroger /* Unregister the /dev/bktrN, tunerN and vbiN devices, 510107699Sroger * the aliases for unit 0 are automatically destroyed */ 51167306Sroger destroy_dev(bktr->vbidev); 51267306Sroger destroy_dev(bktr->tunerdev); 51367306Sroger destroy_dev(bktr->bktrdev); 51467306Sroger 51551694Sroger /* 51651694Sroger * Deallocate resources. 51751694Sroger */ 51851694Sroger bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 51965049Sroger bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 52065049Sroger bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 52165049Sroger 52251694Sroger return 0; 52351694Sroger} 52451694Sroger 52551694Sroger/* 52651694Sroger * the shutdown routine. 52751694Sroger */ 52851694Srogerstatic int 52951694Srogerbktr_shutdown( device_t dev ) 53051694Sroger{ 53151694Sroger struct bktr_softc *bktr = device_get_softc(dev); 53251694Sroger 53351694Sroger /* Disable the brooktree device */ 53459014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53559014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 53651694Sroger 53751694Sroger return 0; 53851694Sroger} 53951694Sroger 54051694Sroger 54151694Sroger/* 54251694Sroger * Special Memory Allocation 54351694Sroger */ 54451694Srogervm_offset_t 54551694Srogerget_bktr_mem( int unit, unsigned size ) 54651694Sroger{ 54751694Sroger vm_offset_t addr = 0; 54851694Sroger 549124507Salc addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 550124507Salc 0xffffffff, 1<<24, 0); 55151694Sroger if (addr == 0) 552124507Salc addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 553124507Salc 0xffffffff, PAGE_SIZE, 0); 55451694Sroger if (addr == 0) { 55551694Sroger printf("bktr%d: Unable to allocate %d bytes of memory.\n", 55651694Sroger unit, size); 55751694Sroger } 55851694Sroger 55951694Sroger return( addr ); 56051694Sroger} 56151694Sroger 56251694Sroger 56351694Sroger/*--------------------------------------------------------- 56451694Sroger** 56551694Sroger** BrookTree 848 character device driver routines 56651694Sroger** 56751694Sroger**--------------------------------------------------------- 56851694Sroger*/ 56951694Sroger 57051694Sroger#define VIDEO_DEV 0x00 57151694Sroger#define TUNER_DEV 0x01 57251694Sroger#define VBI_DEV 0x02 57351694Sroger 57451694Sroger#define UNIT(x) ((x) & 0x0f) 57551694Sroger#define FUNCTION(x) (x >> 4) 57651694Sroger 57751694Sroger/* 57851694Sroger * 57951694Sroger */ 580104094Sphkstatic int 581130585Sphkbktr_open( struct cdev *dev, int flags, int fmt, struct thread *td ) 58251694Sroger{ 58351694Sroger bktr_ptr_t bktr; 58451694Sroger int unit; 58551694Sroger int result; 58651694Sroger 587183397Sed unit = UNIT( dev2unit(dev) ); 58851694Sroger 58951694Sroger /* Get the device data */ 59051694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 59151694Sroger if (bktr == NULL) { 59251694Sroger /* the device is no longer valid/functioning */ 59351694Sroger return (ENXIO); 59451694Sroger } 59551694Sroger 59651694Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 59751694Sroger return( ENXIO ); 59851694Sroger 59951694Sroger /* Record that the device is now busy */ 60051694Sroger device_busy(devclass_get_device(bktr_devclass, unit)); 60151694Sroger 60251694Sroger 60351694Sroger if (bt848_card != -1) { 60451694Sroger if ((bt848_card >> 8 == unit ) && 60551694Sroger ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 60651694Sroger if ( bktr->bt848_card != (bt848_card & 0xff) ) { 60751694Sroger bktr->bt848_card = (bt848_card & 0xff); 60851694Sroger probeCard(bktr, FALSE, unit); 60951694Sroger } 61051694Sroger } 61151694Sroger } 61251694Sroger 61351694Sroger if (bt848_tuner != -1) { 61451694Sroger if ((bt848_tuner >> 8 == unit ) && 61551694Sroger ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 61651694Sroger if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 61751694Sroger bktr->bt848_tuner = (bt848_tuner & 0xff); 61851694Sroger probeCard(bktr, FALSE, unit); 61951694Sroger } 62051694Sroger } 62151694Sroger } 62251694Sroger 62351694Sroger if (bt848_reverse_mute != -1) { 62459014Sroger if ((bt848_reverse_mute >> 8) == unit ) { 62551694Sroger bktr->reverse_mute = bt848_reverse_mute & 0xff; 62651694Sroger } 62751694Sroger } 62851694Sroger 62959014Sroger if (bt848_slow_msp_audio != -1) { 63059014Sroger if ((bt848_slow_msp_audio >> 8) == unit ) { 63159014Sroger bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 63259014Sroger } 63359014Sroger } 63459014Sroger 635118819Salex#ifdef BKTR_NEW_MSP34XX_DRIVER 636118819Salex if (bt848_stereo_once != 0) { 637118819Salex if ((bt848_stereo_once >> 8) == unit ) { 638118819Salex bktr->stereo_once = (bt848_stereo_once & 0xff); 639118819Salex } 640118819Salex } 641118819Salex 642118819Salex if (bt848_amsound != -1) { 643118819Salex if ((bt848_amsound >> 8) == unit ) { 644118819Salex bktr->amsound = (bt848_amsound & 0xff); 645118819Salex } 646118819Salex } 647118819Salex 648118819Salex if (bt848_dolby != -1) { 649118819Salex if ((bt848_dolby >> 8) == unit ) { 650118819Salex bktr->dolby = (bt848_dolby & 0xff); 651118819Salex } 652118819Salex } 653118819Salex#endif 654118819Salex 655183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 65651694Sroger case VIDEO_DEV: 65751694Sroger result = video_open( bktr ); 65851694Sroger break; 65951694Sroger case TUNER_DEV: 66051694Sroger result = tuner_open( bktr ); 66151694Sroger break; 66251694Sroger case VBI_DEV: 66351694Sroger result = vbi_open( bktr ); 66451694Sroger break; 66551694Sroger default: 66651694Sroger result = ENXIO; 66751694Sroger break; 66851694Sroger } 66951694Sroger 67051694Sroger /* If there was an error opening the device, undo the busy status */ 67151694Sroger if (result != 0) 67251694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 67351694Sroger return( result ); 67451694Sroger} 67551694Sroger 67651694Sroger 67751694Sroger/* 67851694Sroger * 67951694Sroger */ 680104094Sphkstatic int 681130585Sphkbktr_close( struct cdev *dev, int flags, int fmt, struct thread *td ) 68251694Sroger{ 68351694Sroger bktr_ptr_t bktr; 68451694Sroger int unit; 68551694Sroger int result; 68651694Sroger 687183397Sed unit = UNIT( dev2unit(dev) ); 68851694Sroger 68951694Sroger /* Get the device data */ 69051694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 69151694Sroger if (bktr == NULL) { 69251694Sroger /* the device is no longer valid/functioning */ 69351694Sroger return (ENXIO); 69451694Sroger } 69551694Sroger 696183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 69751694Sroger case VIDEO_DEV: 69851694Sroger result = video_close( bktr ); 69951694Sroger break; 70051694Sroger case TUNER_DEV: 70151694Sroger result = tuner_close( bktr ); 70251694Sroger break; 70351694Sroger case VBI_DEV: 70451694Sroger result = vbi_close( bktr ); 70551694Sroger break; 70651694Sroger default: 70751694Sroger return (ENXIO); 70851694Sroger break; 70951694Sroger } 71051694Sroger 71151694Sroger device_unbusy(devclass_get_device(bktr_devclass, unit)); 71251694Sroger return( result ); 71351694Sroger} 71451694Sroger 71551694Sroger 71651694Sroger/* 71751694Sroger * 71851694Sroger */ 719104094Sphkstatic int 720130585Sphkbktr_read( struct cdev *dev, struct uio *uio, int ioflag ) 72151694Sroger{ 72251694Sroger bktr_ptr_t bktr; 72351694Sroger int unit; 72451694Sroger 725183397Sed unit = UNIT(dev2unit(dev)); 72651694Sroger 72751694Sroger /* Get the device data */ 72851694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 72951694Sroger if (bktr == NULL) { 73051694Sroger /* the device is no longer valid/functioning */ 73151694Sroger return (ENXIO); 73251694Sroger } 73351694Sroger 734183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 73551694Sroger case VIDEO_DEV: 73651694Sroger return( video_read( bktr, unit, dev, uio ) ); 73751694Sroger case VBI_DEV: 73851694Sroger return( vbi_read( bktr, uio, ioflag ) ); 73951694Sroger } 74051694Sroger return( ENXIO ); 74151694Sroger} 74251694Sroger 74351694Sroger 74451694Sroger/* 74551694Sroger * 74651694Sroger */ 747104094Sphkstatic int 748130585Sphkbktr_write( struct cdev *dev, struct uio *uio, int ioflag ) 74951694Sroger{ 75051694Sroger return( EINVAL ); /* XXX or ENXIO ? */ 75151694Sroger} 75251694Sroger 75351694Sroger 75451694Sroger/* 75551694Sroger * 75651694Sroger */ 757104094Sphkstatic int 758130585Sphkbktr_ioctl( struct cdev *dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 75951694Sroger{ 76051694Sroger bktr_ptr_t bktr; 76151694Sroger int unit; 76251694Sroger 763183397Sed unit = UNIT(dev2unit(dev)); 76451694Sroger 76551694Sroger /* Get the device data */ 76651694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76751694Sroger if (bktr == NULL) { 76851694Sroger /* the device is no longer valid/functioning */ 76951694Sroger return (ENXIO); 77051694Sroger } 77151694Sroger 772158937Sjmg#ifdef BKTR_GPIO_ACCESS 773158937Sjmg if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN && 774158937Sjmg cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA && 775158937Sjmg cmd != BT848_GPIO_SET_DATA) /* no frame buffer allocated (ioctl failed) */ 776158937Sjmg return( ENOMEM ); 777158937Sjmg#else 77851694Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 77951694Sroger return( ENOMEM ); 780158937Sjmg#endif 78151694Sroger 782183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 78351694Sroger case VIDEO_DEV: 78483366Sjulian return( video_ioctl( bktr, unit, cmd, arg, td ) ); 78551694Sroger case TUNER_DEV: 78683366Sjulian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 78751694Sroger } 78851694Sroger 78951694Sroger return( ENXIO ); 79051694Sroger} 79151694Sroger 79251694Sroger 79351694Sroger/* 79451694Sroger * 79551694Sroger */ 796104094Sphkstatic int 797130585Sphkbktr_mmap( struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 79851694Sroger{ 79951694Sroger int unit; 80051694Sroger bktr_ptr_t bktr; 80151694Sroger 802183397Sed unit = UNIT(dev2unit(dev)); 80351694Sroger 804183397Sed if (FUNCTION(dev2unit(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 80551694Sroger return( -1 ); 80651694Sroger 80751694Sroger /* Get the device data */ 80851694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 80951694Sroger if (bktr == NULL) { 81051694Sroger /* the device is no longer valid/functioning */ 81151694Sroger return (ENXIO); 81251694Sroger } 81351694Sroger 81451694Sroger if (nprot & PROT_EXEC) 81551694Sroger return( -1 ); 81651694Sroger 81751694Sroger if (offset < 0) 81851694Sroger return( -1 ); 81951694Sroger 82051694Sroger if (offset >= bktr->alloc_pages * PAGE_SIZE) 82151694Sroger return( -1 ); 82251694Sroger 823111462Smux *paddr = vtophys(bktr->bigbuf) + offset; 824111462Smux return( 0 ); 82551694Sroger} 82651694Sroger 827104094Sphkstatic int 828130585Sphkbktr_poll( struct cdev *dev, int events, struct thread *td) 82951694Sroger{ 83051694Sroger int unit; 83151694Sroger bktr_ptr_t bktr; 83251694Sroger int revents = 0; 83359277Sroger DECLARE_INTR_MASK(s); 83451694Sroger 835183397Sed unit = UNIT(dev2unit(dev)); 83651694Sroger 83751694Sroger /* Get the device data */ 83851694Sroger bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 83951694Sroger if (bktr == NULL) { 84051694Sroger /* the device is no longer valid/functioning */ 84151694Sroger return (ENXIO); 84251694Sroger } 84351694Sroger 844123088Struckman LOCK_VBI(bktr); 84559277Sroger DISABLE_INTR(s); 84651694Sroger 84751694Sroger if (events & (POLLIN | POLLRDNORM)) { 84851694Sroger 849183397Sed switch ( FUNCTION( dev2unit(dev) ) ) { 85051694Sroger case VBI_DEV: 85151694Sroger if(bktr->vbisize == 0) 85283366Sjulian selrecord(td, &bktr->vbi_select); 85351694Sroger else 85451694Sroger revents |= events & (POLLIN | POLLRDNORM); 85551694Sroger break; 85651694Sroger } 85751694Sroger } 85851694Sroger 85959250Sroger ENABLE_INTR(s); 860123088Struckman UNLOCK_VBI(bktr); 86151694Sroger 86251694Sroger return (revents); 86351694Sroger} 86451694Sroger 86551694Sroger/*****************/ 86651694Sroger/* *** BSDI *** */ 86751694Sroger/*****************/ 86851694Sroger 86951694Sroger#if defined(__bsdi__) 87051694Sroger#endif /* __bsdi__ BSDI specific kernel interface routines */ 87151694Sroger 87251694Sroger 87351694Sroger/*****************************/ 87451694Sroger/* *** OpenBSD / NetBSD *** */ 87551694Sroger/*****************************/ 87651694Sroger#if defined(__NetBSD__) || defined(__OpenBSD__) 87759014Sroger 87859014Sroger#define IPL_VIDEO IPL_BIO /* XXX */ 87959014Sroger 88059014Srogerstatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 88159014Sroger 88259014Sroger#define bktr_open bktropen 88359014Sroger#define bktr_close bktrclose 88459014Sroger#define bktr_read bktrread 88559014Sroger#define bktr_write bktrwrite 88659014Sroger#define bktr_ioctl bktrioctl 88759014Sroger#define bktr_mmap bktrmmap 88859014Sroger 88959014Srogervm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 89059014Sroger vm_offset_t, vm_offset_t); 89159014Sroger 89262112Sroger#if defined(__OpenBSD__) 89392739Salfredstatic int bktr_probe(struct device *, void *, void *); 89459014Sroger#else 89592739Salfredstatic int bktr_probe(struct device *, struct cfdata *, void *); 89659014Sroger#endif 89792739Salfredstatic void bktr_attach(struct device *, struct device *, void *); 89859014Sroger 89959014Srogerstruct cfattach bktr_ca = { 90059014Sroger sizeof(struct bktr_softc), bktr_probe, bktr_attach 90159014Sroger}; 90259014Sroger 90359014Sroger#if defined(__NetBSD__) 90459014Srogerextern struct cfdriver bktr_cd; 90559014Sroger#else 90659014Srogerstruct cfdriver bktr_cd = { 90759014Sroger NULL, "bktr", DV_DULL 90859014Sroger}; 90959014Sroger#endif 91059014Sroger 91162112Srogerint 91262112Srogerbktr_probe(parent, match, aux) 91362112Sroger struct device *parent; 91462112Sroger#if defined(__OpenBSD__) 91559014Sroger void *match; 91659014Sroger#else 91759014Sroger struct cfdata *match; 91859014Sroger#endif 91959014Sroger void *aux; 92059014Sroger{ 92159014Sroger struct pci_attach_args *pa = aux; 92259014Sroger 92359014Sroger if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 92459014Sroger (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 92559014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 92659014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 92759014Sroger PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 92859014Sroger return 1; 92959014Sroger 93059014Sroger return 0; 93159014Sroger} 93259014Sroger 93359014Sroger 93459014Sroger/* 93559014Sroger * the attach routine. 93659014Sroger */ 93759014Srogerstatic void 93862112Srogerbktr_attach(struct device *parent, struct device *self, void *aux) 93959014Sroger{ 94059014Sroger bktr_ptr_t bktr; 94159014Sroger u_long latency; 94259014Sroger u_long fun; 94359014Sroger unsigned int rev; 94459014Sroger 94559014Sroger#if defined(__OpenBSD__) 94659014Sroger struct pci_attach_args *pa = aux; 94759014Sroger pci_chipset_tag_t pc = pa->pa_pc; 94859014Sroger 94959014Sroger pci_intr_handle_t ih; 95059014Sroger const char *intrstr; 95159014Sroger int retval; 95259014Sroger int unit; 95359014Sroger 95459014Sroger bktr = (bktr_ptr_t)self; 95559014Sroger unit = bktr->bktr_dev.dv_unit; 95659014Sroger 95759014Sroger bktr->pc = pa->pa_pc; 95859014Sroger bktr->tag = pa->pa_tag; 95959014Sroger bktr->dmat = pa->pa_dmat; 96059014Sroger 96159014Sroger /* 96259014Sroger * map memory 96359014Sroger */ 96459014Sroger bktr->memt = pa->pa_memt; 96559014Sroger retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 96659014Sroger &bktr->phys_base, &bktr->obmemsz, NULL); 96759014Sroger if (!retval) 96859014Sroger retval = bus_space_map(pa->pa_memt, bktr->phys_base, 96959014Sroger bktr->obmemsz, 0, &bktr->memh); 97059014Sroger if (retval) { 97159014Sroger printf(": couldn't map memory\n"); 97259014Sroger return; 97359014Sroger } 97459014Sroger 97559014Sroger 97659014Sroger /* 97759014Sroger * map interrupt 97859014Sroger */ 97959014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 98059014Sroger pa->pa_intrline, &ih)) { 98159014Sroger printf(": couldn't map interrupt\n"); 98259014Sroger return; 98359014Sroger } 98459014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 98559014Sroger 98659014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 98759014Sroger bktr_intr, bktr, bktr->bktr_dev.dv_xname); 98859014Sroger if (bktr->ih == NULL) { 98959014Sroger printf(": couldn't establish interrupt"); 99059014Sroger if (intrstr != NULL) 99159014Sroger printf(" at %s", intrstr); 99259014Sroger printf("\n"); 99359014Sroger return; 99459014Sroger } 99559014Sroger 99659014Sroger if (intrstr != NULL) 99759014Sroger printf(": %s\n", intrstr); 99859014Sroger#endif /* __OpenBSD__ */ 99959014Sroger 100059014Sroger#if defined(__NetBSD__) 100159014Sroger struct pci_attach_args *pa = aux; 100259014Sroger pci_intr_handle_t ih; 100359014Sroger const char *intrstr; 100459014Sroger int retval; 100559014Sroger int unit; 100659014Sroger 100759014Sroger bktr = (bktr_ptr_t)self; 100859014Sroger unit = bktr->bktr_dev.dv_unit; 100959014Sroger bktr->dmat = pa->pa_dmat; 101059014Sroger 101159014Sroger printf("\n"); 101259014Sroger 101359014Sroger /* 101459014Sroger * map memory 101559014Sroger */ 101659014Sroger retval = pci_mapreg_map(pa, PCI_MAPREG_START, 101762112Sroger PCI_MAPREG_TYPE_MEM 101862112Sroger | PCI_MAPREG_MEM_TYPE_32BIT, 0, 101962112Sroger &bktr->memt, &bktr->memh, NULL, 102062112Sroger &bktr->obmemsz); 102162112Sroger DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 102262112Sroger bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 102359014Sroger if (retval) { 102462112Sroger printf("%s: couldn't map memory\n", bktr_name(bktr)); 102559014Sroger return; 102659014Sroger } 102759014Sroger 102859014Sroger /* 102959014Sroger * Disable the brooktree device 103059014Sroger */ 103159014Sroger OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 103259014Sroger OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 103359014Sroger 103459014Sroger /* 103559014Sroger * map interrupt 103659014Sroger */ 103759014Sroger if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 103859014Sroger pa->pa_intrline, &ih)) { 103962112Sroger printf("%s: couldn't map interrupt\n", 104062112Sroger bktr_name(bktr)); 104159014Sroger return; 104259014Sroger } 104359014Sroger intrstr = pci_intr_string(pa->pa_pc, ih); 104459014Sroger bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 104559014Sroger bktr_intr, bktr); 104659014Sroger if (bktr->ih == NULL) { 104759014Sroger printf("%s: couldn't establish interrupt", 104862112Sroger bktr_name(bktr)); 104962112Sroger if (intrstr != NULL) 105062112Sroger printf(" at %s", intrstr); 105162112Sroger printf("\n"); 105262112Sroger return; 105359014Sroger } 105459014Sroger if (intrstr != NULL) 105562112Sroger printf("%s: interrupting at %s\n", bktr_name(bktr), 105659014Sroger intrstr); 105759014Sroger#endif /* __NetBSD__ */ 105859014Sroger 105959014Sroger/* 106059014Sroger * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 106159014Sroger * you have more than four, then 16 would probably be a better value. 106259014Sroger */ 106359014Sroger#ifndef BROOKTREE_DEF_LATENCY_VALUE 106459014Sroger#define BROOKTREE_DEF_LATENCY_VALUE 10 106559014Sroger#endif 106659014Sroger latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 106759014Sroger latency = (latency >> 8) & 0xff; 106859014Sroger 106962112Sroger if (!latency) { 107062112Sroger if (bootverbose) { 107159014Sroger printf("%s: PCI bus latency was 0 changing to %d", 107262112Sroger bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 107359014Sroger } 107459014Sroger latency = BROOKTREE_DEF_LATENCY_VALUE; 107559014Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, 107659014Sroger PCI_LATENCY_TIMER, latency<<8); 107759014Sroger } 107859014Sroger 107959014Sroger 108062112Sroger /* Enabled Bus Master 108162112Sroger XXX: check if all old DMA is stopped first (e.g. after warm 108262112Sroger boot) */ 108359014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 108462112Sroger pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 108562112Sroger fun | PCI_COMMAND_MASTER_ENABLE); 108659014Sroger 108759014Sroger /* read the pci id and determine the card type */ 108859014Sroger fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 108959014Sroger rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 109059014Sroger 109162112Sroger common_bktr_attach(bktr, unit, fun, rev); 109259014Sroger} 109359014Sroger 109459014Sroger 109559014Sroger/* 109659014Sroger * Special Memory Allocation 109759014Sroger */ 109859014Srogervm_offset_t 109959014Srogerget_bktr_mem(bktr, dmapp, size) 110059014Sroger bktr_ptr_t bktr; 110159014Sroger bus_dmamap_t *dmapp; 110259014Sroger unsigned int size; 110359014Sroger{ 110459014Sroger bus_dma_tag_t dmat = bktr->dmat; 110559014Sroger bus_dma_segment_t seg; 110659014Sroger bus_size_t align; 110759014Sroger int rseg; 110859014Sroger caddr_t kva; 110959014Sroger 111059014Sroger /* 111159014Sroger * Allocate a DMA area 111259014Sroger */ 111359014Sroger align = 1 << 24; 111459014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111559014Sroger &rseg, BUS_DMA_NOWAIT)) { 111659014Sroger align = PAGE_SIZE; 111759014Sroger if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111859014Sroger &rseg, BUS_DMA_NOWAIT)) { 111962112Sroger printf("%s: Unable to dmamem_alloc of %d bytes\n", 112062112Sroger bktr_name(bktr), size); 112159014Sroger return 0; 112259014Sroger } 112359014Sroger } 112459014Sroger if (bus_dmamem_map(dmat, &seg, rseg, size, 112559014Sroger &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 112662112Sroger printf("%s: Unable to dmamem_map of %d bytes\n", 112762112Sroger bktr_name(bktr), size); 112859014Sroger bus_dmamem_free(dmat, &seg, rseg); 112959014Sroger return 0; 113059014Sroger } 113159014Sroger#ifdef __OpenBSD__ 113259014Sroger bktr->dm_mapsize = size; 113359014Sroger#endif 113459014Sroger /* 113559014Sroger * Create and locd the DMA map for the DMA area 113659014Sroger */ 113759014Sroger if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 113862112Sroger printf("%s: Unable to dmamap_create of %d bytes\n", 113962112Sroger bktr_name(bktr), size); 114059014Sroger bus_dmamem_unmap(dmat, kva, size); 114159014Sroger bus_dmamem_free(dmat, &seg, rseg); 114259014Sroger return 0; 114359014Sroger } 114459014Sroger if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 114562112Sroger printf("%s: Unable to dmamap_load of %d bytes\n", 114662112Sroger bktr_name(bktr), size); 114759014Sroger bus_dmamem_unmap(dmat, kva, size); 114859014Sroger bus_dmamem_free(dmat, &seg, rseg); 114959014Sroger bus_dmamap_destroy(dmat, *dmapp); 115059014Sroger return 0; 115159014Sroger } 115259014Sroger return (vm_offset_t)kva; 115359014Sroger} 115459014Sroger 115559014Srogervoid 115659014Srogerfree_bktr_mem(bktr, dmap, kva) 115759014Sroger bktr_ptr_t bktr; 115859014Sroger bus_dmamap_t dmap; 115959014Sroger vm_offset_t kva; 116059014Sroger{ 116159014Sroger bus_dma_tag_t dmat = bktr->dmat; 116259014Sroger 116359014Sroger#ifdef __NetBSD__ 116459014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 116559014Sroger#else 116659014Sroger bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 116759014Sroger#endif 116859014Sroger bus_dmamem_free(dmat, dmap->dm_segs, 1); 116959014Sroger bus_dmamap_destroy(dmat, dmap); 117059014Sroger} 117159014Sroger 117259014Sroger 117359014Sroger/*--------------------------------------------------------- 117459014Sroger** 117559014Sroger** BrookTree 848 character device driver routines 117659014Sroger** 117759014Sroger**--------------------------------------------------------- 117859014Sroger*/ 117959014Sroger 118059014Sroger 118159014Sroger#define VIDEO_DEV 0x00 118259014Sroger#define TUNER_DEV 0x01 118359014Sroger#define VBI_DEV 0x02 118459014Sroger 1185183397Sed#define UNIT(x) (dev2unit((x) & 0x0f)) 1186183397Sed#define FUNCTION(x) (dev2unit((x >> 4) & 0x0f)) 118759014Sroger 118859014Sroger/* 118959014Sroger * 119059014Sroger */ 119159014Srogerint 119283366Sjulianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 119359014Sroger{ 119459014Sroger bktr_ptr_t bktr; 119559014Sroger int unit; 119659014Sroger 119762112Sroger unit = UNIT(dev); 119859014Sroger 119959014Sroger /* unit out of range */ 120059014Sroger if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 120162112Sroger return(ENXIO); 120259014Sroger 120359014Sroger bktr = bktr_cd.cd_devs[unit]; 120459014Sroger 120559014Sroger if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 120662112Sroger return(ENXIO); 120759014Sroger 120862112Sroger switch (FUNCTION(dev)) { 120959014Sroger case VIDEO_DEV: 121062112Sroger return(video_open(bktr)); 121159014Sroger case TUNER_DEV: 121262112Sroger return(tuner_open(bktr)); 121359014Sroger case VBI_DEV: 121462112Sroger return(vbi_open(bktr)); 121559014Sroger } 121659014Sroger 121762112Sroger return(ENXIO); 121859014Sroger} 121959014Sroger 122059014Sroger 122159014Sroger/* 122259014Sroger * 122359014Sroger */ 122459014Srogerint 122583366Sjulianbktr_close(dev_t dev, int flags, int fmt, struct thread *td) 122659014Sroger{ 122759014Sroger bktr_ptr_t bktr; 122859014Sroger int unit; 122959014Sroger 123062112Sroger unit = UNIT(dev); 123159014Sroger 123259014Sroger bktr = bktr_cd.cd_devs[unit]; 123359014Sroger 123462112Sroger switch (FUNCTION(dev)) { 123559014Sroger case VIDEO_DEV: 123662112Sroger return(video_close(bktr)); 123759014Sroger case TUNER_DEV: 123862112Sroger return(tuner_close(bktr)); 123959014Sroger case VBI_DEV: 124062112Sroger return(vbi_close(bktr)); 124159014Sroger } 124259014Sroger 124362112Sroger return(ENXIO); 124459014Sroger} 124559014Sroger 124659014Sroger/* 124759014Sroger * 124859014Sroger */ 124959014Srogerint 125062112Srogerbktr_read(dev_t dev, struct uio *uio, int ioflag) 125159014Sroger{ 125259014Sroger bktr_ptr_t bktr; 125359014Sroger int unit; 125459014Sroger 125562112Sroger unit = UNIT(dev); 125659014Sroger 125759014Sroger bktr = bktr_cd.cd_devs[unit]; 125859014Sroger 125962112Sroger switch (FUNCTION(dev)) { 126059014Sroger case VIDEO_DEV: 126162112Sroger return(video_read(bktr, unit, dev, uio)); 126259014Sroger case VBI_DEV: 126362112Sroger return(vbi_read(bktr, uio, ioflag)); 126459014Sroger } 126559014Sroger 126662112Sroger return(ENXIO); 126759014Sroger} 126859014Sroger 126959014Sroger 127059014Sroger/* 127159014Sroger * 127259014Sroger */ 127359014Srogerint 127462112Srogerbktr_write(dev_t dev, struct uio *uio, int ioflag) 127559014Sroger{ 127659014Sroger /* operation not supported */ 127762112Sroger return(EOPNOTSUPP); 127859014Sroger} 127959014Sroger 128059014Sroger/* 128159014Sroger * 128259014Sroger */ 128359014Srogerint 128483366Sjulianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 128559014Sroger{ 128659014Sroger bktr_ptr_t bktr; 128759014Sroger int unit; 128859014Sroger 128962112Sroger unit = UNIT(dev); 129059014Sroger 129159014Sroger bktr = bktr_cd.cd_devs[unit]; 129259014Sroger 129359014Sroger if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 129462112Sroger return(ENOMEM); 129559014Sroger 129662112Sroger switch (FUNCTION(dev)) { 129759014Sroger case VIDEO_DEV: 129862112Sroger return(video_ioctl(bktr, unit, cmd, arg, pr)); 129959014Sroger case TUNER_DEV: 130062112Sroger return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 130159014Sroger } 130259014Sroger 130362112Sroger return(ENXIO); 130459014Sroger} 130559014Sroger 130659014Sroger/* 130759014Sroger * 130859014Sroger */ 130962214Srogerpaddr_t 131062214Srogerbktr_mmap(dev_t dev, off_t offset, int nprot) 131159014Sroger{ 131259014Sroger int unit; 131359014Sroger bktr_ptr_t bktr; 131459014Sroger 131562112Sroger unit = UNIT(dev); 131659014Sroger 131762112Sroger if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 131862112Sroger return(-1); 131959014Sroger 132059014Sroger bktr = bktr_cd.cd_devs[unit]; 132159014Sroger 132262112Sroger if ((vaddr_t)offset < 0) 132362112Sroger return(-1); 132459014Sroger 132562112Sroger if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 132662112Sroger return(-1); 132759014Sroger 132859014Sroger#ifdef __NetBSD__ 132959014Sroger return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 133062112Sroger (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 133159014Sroger#else 133262112Sroger return(i386_btop(vtophys(bktr->bigbuf) + offset)); 133359014Sroger#endif 133459014Sroger} 133559014Sroger 133651694Sroger#endif /* __NetBSD__ || __OpenBSD__ */ 1337