bktr_os.c revision 123291
16059Samurai/*- 26059Samurai * 1. Redistributions of source code must retain the 36059Samurai * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 46059Samurai * All rights reserved. 56059Samurai * 66059Samurai * Redistribution and use in source and binary forms, with or without 76059Samurai * modification, are permitted provided that the following conditions 86059Samurai * are met: 96059Samurai * 1. Redistributions of source code must retain the above copyright 106059Samurai * notice, this list of conditions and the following disclaimer. 116059Samurai * 2. Redistributions in binary form must reproduce the above copyright 126059Samurai * notice, this list of conditions and the following disclaimer in the 136059Samurai * documentation and/or other materials provided with the distribution. 146059Samurai * 3. All advertising materials mentioning features or use of this software 156059Samurai * must display the following acknowledgement: 166059Samurai * This product includes software developed by Amancio Hasty and 176059Samurai * Roger Hardiman 186059Samurai * 4. The name of the author may not be used to endorse or promote products 198857Srgrimes * derived from this software without specific prior written permission. 2031598Sbrian * 218857Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 226059Samurai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2330715Sbrian * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2430715Sbrian * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2526031Sbrian * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2630715Sbrian * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2726031Sbrian * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2830715Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2926031Sbrian * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3030715Sbrian * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3130715Sbrian * POSSIBILITY OF SUCH DAMAGE. 3231343Sbrian */ 3326031Sbrian 3431343Sbrian#include <sys/cdefs.h> 3530715Sbrian__FBSDID("$FreeBSD: head/sys/dev/bktr/bktr_os.c 123291 2003-12-08 07:59:18Z obrien $"); 3630715Sbrian 3726516Sbrian/* 3830715Sbrian * This is part of the Driver for Video Capture Cards (Frame grabbers) 3930715Sbrian * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 4030715Sbrian * chipset. 4130715Sbrian * Copyright Roger Hardiman and Amancio Hasty. 4230715Sbrian * 4330715Sbrian * bktr_os : This has all the Operating System dependant code, 4430715Sbrian * probe/attach and open/close/ioctl/read/mmap 4530715Sbrian * memory allocation 4630715Sbrian * PCI bus interfacing 4730715Sbrian */ 4831343Sbrian 4930715Sbrian#include "opt_bktr.h" /* include any kernel config options */ 5030715Sbrian 5130715Sbrian#define FIFO_RISC_DISABLED 0 5230715Sbrian#define ALL_INTS_DISABLED 0 536059Samurai 546059Samurai 556059Samurai/*******************/ 566059Samurai/* *** FreeBSD *** */ 576059Samurai/*******************/ 5813389Sphk#ifdef __FreeBSD__ 5931343Sbrian 6026031Sbrian#include <sys/param.h> 6131343Sbrian#include <sys/systm.h> 626059Samurai#include <sys/conf.h> 6326142Sbrian#include <sys/uio.h> 646059Samurai#include <sys/kernel.h> 6525630Sbrian#include <sys/signalvar.h> 6625630Sbrian#include <sys/mman.h> 676059Samurai#include <sys/poll.h> 6826940Sbrian#if __FreeBSD_version >= 500014 6930715Sbrian#include <sys/selinfo.h> 7030715Sbrian#else 7130715Sbrian#include <sys/select.h> 7230733Sbrian#endif 7330715Sbrian#include <sys/vnode.h> 7431080Sbrian 756059Samurai#include <vm/vm.h> 766059Samurai#include <vm/vm_kern.h> 776059Samurai#include <vm/pmap.h> 7831343Sbrian#include <vm/vm_extern.h> 7931343Sbrian 8031343Sbrian#if (__FreeBSD_version >=400000) 8131343Sbrian#include <sys/bus.h> /* used by smbus and newbus */ 8231343Sbrian#endif 8331343Sbrian 8431343Sbrian#if (__FreeBSD_version >=300000) 8531343Sbrian#include <machine/bus_memio.h> /* used by bus space */ 8631343Sbrian#include <machine/bus.h> /* used by bus space and newbus */ 8731343Sbrian#include <sys/bus.h> 8831343Sbrian#endif 8931343Sbrian 9031343Sbrian#if (__FreeBSD_version >=400000) 9131343Sbrian#include <sys/rman.h> /* used by newbus */ 9231343Sbrian#include <machine/resource.h> /* used by newbus */ 9331343Sbrian#endif 9431343Sbrian 956059Samurai#if (__FreeBSD_version < 500000) 966059Samurai#include <machine/clock.h> /* for DELAY */ 9731343Sbrian#include <pci/pcivar.h> 986059Samurai#include <pci/pcireg.h> 9928679Sbrian#else 10031372Sbrian#include <dev/pci/pcivar.h> 1016059Samurai#include <dev/pci/pcireg.h> 10226516Sbrian#endif 10326516Sbrian 10426516Sbrian#include <sys/sysctl.h> 10531343Sbrianint bt848_card = -1; 10631343Sbrianint bt848_tuner = -1; 10731372Sbrianint bt848_reverse_mute = -1; 10831372Sbrianint bt848_format = -1; 10928679Sbrianint bt848_slow_msp_audio = -1; 11028679Sbrian#ifdef BKTR_NEW_MSP34XX_DRIVER 1116059Samuraiint bt848_stereo_once = 0; /* no continuous stereo monitoring */ 11226516Sbrianint bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 1136059Samurai the autoscan seems work well only with FM... */ 11431372Sbrianint bt848_dolby = 0; 11531372Sbrian#endif 11631372Sbrian 11731372SbrianSYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 11831372SbrianSYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 11931372SbrianSYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 12031372SbrianSYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 12131372SbrianSYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 12231372SbrianSYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 12331372Sbrian#ifdef BKTR_NEW_MSP34XX_DRIVER 1246059SamuraiSYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 12531343SbrianSYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 1266764SamuraiSYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 12731372Sbrian#endif 12831372Sbrian 12931372Sbrian#endif /* end freebsd section */ 13031372Sbrian 1316059Samurai 13231372Sbrian 13326516Sbrian/****************/ 13426516Sbrian/* *** BSDI *** */ 13526516Sbrian/****************/ 1366059Samurai#ifdef __bsdi__ 1376059Samurai#endif /* __bsdi__ */ 1386059Samurai 13930913Sbrian 1406059Samurai/**************************/ 14131343Sbrian/* *** OpenBSD/NetBSD *** */ 1426059Samurai/**************************/ 14320120Snate#if defined(__NetBSD__) || defined(__OpenBSD__) 14420120Snate 14525908Sbrian#include <sys/param.h> 14625908Sbrian#include <sys/systm.h> 14720120Snate#include <sys/conf.h> 14810528Samurai#include <sys/uio.h> 1496059Samurai#include <sys/kernel.h> 15010528Samurai#include <sys/signalvar.h> 1516059Samurai#include <sys/mman.h> 15210528Samurai#include <sys/poll.h> 1536059Samurai#include <sys/select.h> 15430913Sbrian#include <sys/vnode.h> 15526516Sbrian 15626516Sbrian#include <vm/vm.h> 1576059Samurai 15826516Sbrian#ifndef __NetBSD__ 1596059Samurai#include <vm/vm_kern.h> 1606059Samurai#include <vm/pmap.h> 1616059Samurai#include <vm/vm_extern.h> 16231343Sbrian#endif 1636059Samurai 16411336Samurai#include <sys/device.h> 16526858Sbrian#include <dev/pci/pcivar.h> 16611336Samurai#include <dev/pci/pcireg.h> 1676059Samurai#include <dev/pci/pcidevs.h> 16826516Sbrian 16926516Sbrian#define BKTR_DEBUG 17026516Sbrian#ifdef BKTR_DEBUG 1716059Samuraiint bktr_debug = 0; 17226516Sbrian#define DPR(x) (bktr_debug ? printf x : 0) 17331343Sbrian#else 17431140Sbrian#define DPR(x) 17531121Sbrian#endif 17611336Samurai#endif /* __NetBSD__ || __OpenBSD__ */ 17711336Samurai 17826516Sbrian 17926516Sbrian#ifdef __NetBSD__ 18031034Sbrian#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 18126516Sbrian#include <dev/pci/bktr/bktr_reg.h> 18228679Sbrian#include <dev/pci/bktr/bktr_tuner.h> 18311336Samurai#include <dev/pci/bktr/bktr_card.h> 18411336Samurai#include <dev/pci/bktr/bktr_audio.h> 18526858Sbrian#include <dev/pci/bktr/bktr_core.h> 18630697Sbrian#include <dev/pci/bktr/bktr_os.h> 18731343Sbrian#else /* Traditional location for .h files */ 18811336Samurai#include <dev/bktr/ioctl_meteor.h> 18911336Samurai#include <dev/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 19026858Sbrian#include <dev/bktr/bktr_reg.h> 19126858Sbrian#include <dev/bktr/bktr_tuner.h> 19211336Samurai#include <dev/bktr/bktr_card.h> 19326516Sbrian#include <dev/bktr/bktr_audio.h> 19426516Sbrian#include <dev/bktr/bktr_core.h> 1956059Samurai#include <dev/bktr/bktr_os.h> 1966059Samurai 19710528Samurai#if defined(BKTR_USE_FREEBSD_SMBUS) 19831343Sbrian#include <dev/bktr/bktr_i2c.h> 19928536Sbrian 20031343Sbrian#include "iicbb_if.h" 20131343Sbrian#include "smbus_if.h" 20228536Sbrian#endif 20331141Sbrian#endif 20431141Sbrian 20531343Sbrian 20628536Sbrian/****************************/ 20731141Sbrian/* *** FreeBSD 4.x code *** */ 20831141Sbrian/****************************/ 20928536Sbrian#if (__FreeBSD_version >= 400000) 21028536Sbrian 21128536Sbrianstatic int bktr_probe( device_t dev ); 21228536Sbrianstatic int bktr_attach( device_t dev ); 21331343Sbrianstatic int bktr_detach( device_t dev ); 21410528Samuraistatic int bktr_shutdown( device_t dev ); 21510528Samuraistatic void bktr_intr(void *arg) { common_bktr_intr(arg); } 21610528Samurai 21726516Sbrianstatic device_method_t bktr_methods[] = { 21831343Sbrian /* Device interface */ 21931343Sbrian DEVMETHOD(device_probe, bktr_probe), 22020813Sjkh DEVMETHOD(device_attach, bktr_attach), 22118856Ssos DEVMETHOD(device_detach, bktr_detach), 22226911Sbrian DEVMETHOD(device_shutdown, bktr_shutdown), 22326516Sbrian 22426516Sbrian#if defined(BKTR_USE_FREEBSD_SMBUS) 22526516Sbrian /* iicbb interface */ 22610528Samurai DEVMETHOD(iicbb_callback, bti2c_iic_callback), 22726911Sbrian DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 22826911Sbrian DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 22928679Sbrian DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 23026911Sbrian DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 23128679Sbrian DEVMETHOD(iicbb_reset, bti2c_iic_reset), 23228679Sbrian 23326911Sbrian /* smbus interface */ 23431121Sbrian DEVMETHOD(smbus_callback, bti2c_smb_callback), 23528679Sbrian DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 23626516Sbrian DEVMETHOD(smbus_writew, bti2c_smb_writew), 23726516Sbrian DEVMETHOD(smbus_readb, bti2c_smb_readb), 23826516Sbrian#endif 23926516Sbrian 24031343Sbrian { 0, 0 } 24128381Sbrian}; 24231121Sbrian 24331121Sbrianstatic driver_t bktr_driver = { 24431121Sbrian "bktr", 24531121Sbrian bktr_methods, 24631121Sbrian sizeof(struct bktr_softc), 24731121Sbrian}; 24828381Sbrian 24928381Sbrianstatic devclass_t bktr_devclass; 25028381Sbrian 25128679Sbrianstatic d_open_t bktr_open; 25228381Sbrianstatic d_close_t bktr_close; 25328381Sbrianstatic d_read_t bktr_read; 25428679Sbrianstatic d_write_t bktr_write; 25526516Sbrianstatic d_ioctl_t bktr_ioctl; 25626516Sbrianstatic d_mmap_t bktr_mmap; 25728679Sbrianstatic d_poll_t bktr_poll; 25828679Sbrian 25918531Sbde#define CDEV_MAJOR 92 26028679Sbrianstatic struct cdevsw bktr_cdevsw = { 26128679Sbrian .d_open = bktr_open, 26228679Sbrian .d_close = bktr_close, 26328679Sbrian .d_read = bktr_read, 26428679Sbrian .d_write = bktr_write, 26528679Sbrian .d_ioctl = bktr_ioctl, 26628679Sbrian .d_poll = bktr_poll, 26728679Sbrian .d_mmap = bktr_mmap, 26826516Sbrian .d_name = "bktr", 26928679Sbrian .d_maj = CDEV_MAJOR, 27028679Sbrian}; 27128679Sbrian 27228679SbrianDRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 27328679Sbrian#if (__FreeBSD_version > 410000) 27428679SbrianMODULE_DEPEND(bktr, bktr_mem, 1,1,1); 27528679SbrianMODULE_VERSION(bktr, 1); 27628679Sbrian#endif 27726516Sbrian 27828679Sbrian 27931343Sbrian/* 28026516Sbrian * the boot time probe routine. 28128679Sbrian */ 28231061Sbrianstatic int 28331343Sbrianbktr_probe( device_t dev ) 28428679Sbrian{ 28531343Sbrian unsigned int type = pci_get_devid(dev); 28631343Sbrian unsigned int rev = pci_get_revid(dev); 28731343Sbrian 28831343Sbrian if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 28931343Sbrian { 29031343Sbrian switch (PCI_PRODUCT(type)) { 29131343Sbrian case PCI_PRODUCT_BROOKTREE_BT848: 29231343Sbrian if (rev == 0x12) 29331343Sbrian device_set_desc(dev, "BrookTree 848A"); 29431343Sbrian else 29531343Sbrian device_set_desc(dev, "BrookTree 848"); 29631343Sbrian return 0; 29728679Sbrian case PCI_PRODUCT_BROOKTREE_BT849: 29828679Sbrian device_set_desc(dev, "BrookTree 849A"); 29910528Samurai return 0; 30028679Sbrian case PCI_PRODUCT_BROOKTREE_BT878: 30128679Sbrian device_set_desc(dev, "BrookTree 878"); 30228974Sbrian return 0; 30328679Sbrian case PCI_PRODUCT_BROOKTREE_BT879: 30428679Sbrian device_set_desc(dev, "BrookTree 879"); 30531125Sbrian return 0; 30631343Sbrian } 30731343Sbrian }; 30830316Sbrian 30930316Sbrian return ENXIO; 31030316Sbrian} 31131343Sbrian 31230316Sbrian 31320813Sjkh/* 31431343Sbrian * the attach routine. 31528679Sbrian */ 31610528Samuraistatic int 31728679Sbrianbktr_attach( device_t dev ) 31826516Sbrian{ 31910528Samurai u_long latency; 32010528Samurai u_long fun; 32128679Sbrian u_long val; 32231343Sbrian unsigned int rev; 32310528Samurai unsigned int unit; 32420813Sjkh int error = 0; 32510528Samurai#ifdef BROOKTREE_IRQ 32620813Sjkh u_long old_irq, new_irq; 32728679Sbrian#endif 32810528Samurai 32910528Samurai struct bktr_softc *bktr = device_get_softc(dev); 33031343Sbrian 33131343Sbrian unit = device_get_unit(dev); 33231343Sbrian 33331343Sbrian /* build the device name for bktr_name() */ 33431343Sbrian snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 33531343Sbrian 33631343Sbrian /* 33731343Sbrian * Enable bus mastering and Memory Mapped device 33831343Sbrian */ 33931343Sbrian val = pci_read_config(dev, PCIR_COMMAND, 4); 34031343Sbrian val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 34131343Sbrian pci_write_config(dev, PCIR_COMMAND, val, 4); 34231343Sbrian 34331343Sbrian /* 34430715Sbrian * Map control/status registers. 34528679Sbrian */ 34628679Sbrian bktr->mem_rid = PCIR_BAR(0); 34728679Sbrian bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 34828679Sbrian 0, ~0, 1, RF_ACTIVE); 34931121Sbrian 35031121Sbrian 35128679Sbrian if (!bktr->res_mem) { 35231372Sbrian device_printf(dev, "could not map memory\n"); 35328679Sbrian error = ENXIO; 35428679Sbrian goto fail; 35528679Sbrian } 35628679Sbrian bktr->memt = rman_get_bustag(bktr->res_mem); 35728679Sbrian bktr->memh = rman_get_bushandle(bktr->res_mem); 35828679Sbrian 35928679Sbrian 36028679Sbrian /* 36128679Sbrian * Disable the brooktree device 36228679Sbrian */ 36328679Sbrian OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 36428679Sbrian OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 36528679Sbrian 36628679Sbrian 36728679Sbrian#ifdef BROOKTREE_IRQ /* from the configuration file */ 36829083Sbrian old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 36928679Sbrian pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 37028679Sbrian new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 37128679Sbrian printf("bktr%d: attach: irq changed from %d to %d\n", 37228679Sbrian unit, (old_irq & 0xff), (new_irq & 0xff)); 37328679Sbrian#endif 37428679Sbrian 37528679Sbrian /* 37628679Sbrian * Allocate our interrupt. 37728679Sbrian */ 37831372Sbrian bktr->irq_rid = 0; 37928679Sbrian bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 38031372Sbrian 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 38131343Sbrian if (bktr->res_irq == NULL) { 38228679Sbrian device_printf(dev, "could not map interrupt\n"); 38328679Sbrian error = ENXIO; 38431343Sbrian goto fail; 38528679Sbrian } 38628679Sbrian 38728679Sbrian error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 38831343Sbrian bktr_intr, bktr, &bktr->res_ih); 38928679Sbrian if (error) { 39028679Sbrian device_printf(dev, "could not setup irq\n"); 39128679Sbrian goto fail; 3926059Samurai 3936059Samurai } 39428536Sbrian 39531343Sbrian 39628536Sbrian /* Update the Device Control Register */ 39728536Sbrian /* on Bt878 and Bt879 cards */ 39828536Sbrian fun = pci_read_config( dev, 0x40, 2); 39928536Sbrian fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 40028536Sbrian 40128536Sbrian#if defined( BKTR_430_FX_MODE ) 40228536Sbrian if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 40328679Sbrian fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 40431343Sbrian#endif 4056059Samurai 4066059Samurai#if defined( BKTR_SIS_VIA_MODE ) 4076059Samurai if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 40826516Sbrian fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 40926516Sbrian OPTi chipset motherboards too */ 41030913Sbrian#endif 41130913Sbrian pci_write_config(dev, 0x40, fun, 2); 41230913Sbrian 41330913Sbrian#if defined(BKTR_USE_FREEBSD_SMBUS) 41426516Sbrian if (bt848_i2c_attach(dev)) 41530913Sbrian printf("bktr%d: i2c_attach: can't attach\n", unit); 41630913Sbrian#endif 41730913Sbrian 41830913Sbrian/* 41930913Sbrian * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 42030913Sbrian * you have more than four, then 16 would probably be a better value. 42126516Sbrian */ 42226516Sbrian#ifndef BROOKTREE_DEF_LATENCY_VALUE 42326516Sbrian#define BROOKTREE_DEF_LATENCY_VALUE 10 4246059Samurai#endif 4256059Samurai latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 42628679Sbrian latency = (latency >> 8) & 0xff; 42731343Sbrian if ( bootverbose ) { 4286059Samurai if (latency) 4296059Samurai printf("brooktree%d: PCI bus latency is", unit); 4306059Samurai else 43126516Sbrian printf("brooktree%d: PCI bus latency was 0 changing to", 43226516Sbrian unit); 4336059Samurai } 43426516Sbrian if ( !latency ) { 43526516Sbrian latency = BROOKTREE_DEF_LATENCY_VALUE; 43628679Sbrian pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 43728679Sbrian } 43828679Sbrian if ( bootverbose ) { 43926516Sbrian printf(" %d.\n", (int) latency); 4406059Samurai } 44131077Sbrian 4426059Samurai /* read the pci device id and revision id */ 4436059Samurai fun = pci_get_devid(dev); 44428679Sbrian rev = pci_get_revid(dev); 44531343Sbrian 4466059Samurai /* call the common attach code */ 44731077Sbrian common_bktr_attach( bktr, unit, fun, rev ); 44831077Sbrian 44931077Sbrian /* make the device entries */ 45031077Sbrian bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 45131077Sbrian 0, 0, 0444, "bktr%d", unit); 4526059Samurai bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 4536059Samurai 0, 0, 0444, "tuner%d", unit); 45428679Sbrian bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 45531343Sbrian 0, 0, 0444, "vbi%d" , unit); 45628327Sbrian 45728327Sbrian 45828327Sbrian /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 45928461Sbrian /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 46028461Sbrian#if (__FreeBSD_version >=500000) 46128461Sbrian if (unit == 0) { 46228461Sbrian bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 46328327Sbrian bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 46428461Sbrian bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 46528461Sbrian } 46628461Sbrian#endif 46728461Sbrian 46828461Sbrian return 0; 46928461Sbrian 47028461Sbrianfail: 47128461Sbrian if (bktr->res_irq) 47228461Sbrian bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 47328461Sbrian if (bktr->res_mem) 47428461Sbrian bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 47528461Sbrian return error; 47628461Sbrian 47728461Sbrian} 47828461Sbrian 47928461Sbrian/* 48031077Sbrian * the detach routine. 48128327Sbrian */ 48228327Sbrianstatic int 48328679Sbrianbktr_detach( device_t dev ) 48431343Sbrian{ 4856059Samurai struct bktr_softc *bktr = device_get_softc(dev); 48626516Sbrian 48726516Sbrian#ifdef BKTR_NEW_MSP34XX_DRIVER 48826516Sbrian /* Disable the soundchip and kernel thread */ 48926516Sbrian if (bktr->msp3400c_info != NULL) 49029840Sbrian msp_detach(bktr); 49129840Sbrian#endif 49229840Sbrian 49331077Sbrian /* Disable the brooktree device */ 4946059Samurai OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 4956059Samurai OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 49628679Sbrian 49731343Sbrian#if defined(BKTR_USE_FREEBSD_SMBUS) 4986059Samurai if (bt848_i2c_detach(dev)) 49931077Sbrian printf("bktr%d: i2c_attach: can't attach\n", 50031077Sbrian device_get_unit(dev)); 50131077Sbrian#endif 5026059Samurai#ifdef USE_VBIMUTEX 5036059Samurai mtx_destroy(&bktr->vbimutex); 50428679Sbrian#endif 50531343Sbrian 50626326Sbrian /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 50731077Sbrian /* The memory is retained by the bktr_mem module so we can unload and */ 50831077Sbrian /* then reload the main bktr driver module */ 50931077Sbrian 51026326Sbrian /* Unregister the /dev/bktrN, tunerN and vbiN devices, 51126326Sbrian * the aliases for unit 0 are automatically destroyed */ 51228679Sbrian destroy_dev(bktr->vbidev); 51331343Sbrian destroy_dev(bktr->tunerdev); 51426326Sbrian destroy_dev(bktr->bktrdev); 51531077Sbrian 51631077Sbrian /* 51731077Sbrian * Deallocate resources. 51831077Sbrian */ 51931077Sbrian bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 52031077Sbrian bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 52126326Sbrian bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 52226326Sbrian 52328679Sbrian return 0; 52431343Sbrian} 52525067Sbrian 52631077Sbrian/* 52731077Sbrian * the shutdown routine. 52831077Sbrian */ 52931077Sbrianstatic int 53025067Sbrianbktr_shutdown( device_t dev ) 53125067Sbrian{ 53228679Sbrian struct bktr_softc *bktr = device_get_softc(dev); 53331343Sbrian 53411336Samurai /* Disable the brooktree device */ 53526516Sbrian OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 53626516Sbrian OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 53726516Sbrian 53811336Samurai return 0; 53911336Samurai} 54026516Sbrian 54128679Sbrian 54226516Sbrian/* 54311336Samurai * Special Memory Allocation 54411336Samurai */ 54526516Sbrianvm_offset_t 54624939Sbrianget_bktr_mem( int unit, unsigned size ) 54724939Sbrian{ 54826516Sbrian vm_offset_t addr = 0; 54928679Sbrian 55026516Sbrian addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 55124939Sbrian if (addr == 0) 55224939Sbrian addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 55311336Samurai if (addr == 0) { 55428679Sbrian printf("bktr%d: Unable to allocate %d bytes of memory.\n", 55511336Samurai unit, size); 55626516Sbrian } 55711336Samurai 55831077Sbrian return( addr ); 55911336Samurai} 56011336Samurai 56126516Sbrian 56228679Sbrian/*--------------------------------------------------------- 56331343Sbrian** 56418752Sjkh** BrookTree 848 character device driver routines 56531077Sbrian** 56631077Sbrian**--------------------------------------------------------- 56731077Sbrian*/ 56831077Sbrian 56931077Sbrian#define VIDEO_DEV 0x00 57031077Sbrian#define TUNER_DEV 0x01 57131077Sbrian#define VBI_DEV 0x02 57231077Sbrian 57318752Sjkh#define UNIT(x) ((x) & 0x0f) 57428679Sbrian#define FUNCTION(x) (x >> 4) 57526516Sbrian 57618752Sjkh/* 57730715Sbrian * 57828679Sbrian */ 57931372Sbrianstatic int 58028679Sbrianbktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 58131372Sbrian{ 58228679Sbrian bktr_ptr_t bktr; 58328679Sbrian int unit; 58428679Sbrian int result; 58531372Sbrian 58628679Sbrian unit = UNIT( minor(dev) ); 58728679Sbrian 58828679Sbrian /* Get the device data */ 58928679Sbrian bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 59028679Sbrian if (bktr == NULL) { 59131372Sbrian /* the device is no longer valid/functioning */ 59228679Sbrian return (ENXIO); 59328679Sbrian } 59428679Sbrian 59528679Sbrian if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 59628679Sbrian return( ENXIO ); 59728679Sbrian 59828679Sbrian /* Record that the device is now busy */ 59931372Sbrian device_busy(devclass_get_device(bktr_devclass, unit)); 60028679Sbrian 60131372Sbrian 60228679Sbrian if (bt848_card != -1) { 60328679Sbrian if ((bt848_card >> 8 == unit ) && 60428679Sbrian ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 60528679Sbrian if ( bktr->bt848_card != (bt848_card & 0xff) ) { 60628679Sbrian bktr->bt848_card = (bt848_card & 0xff); 60728679Sbrian probeCard(bktr, FALSE, unit); 60828679Sbrian } 60928679Sbrian } 61028679Sbrian } 61128679Sbrian 61228679Sbrian if (bt848_tuner != -1) { 61328679Sbrian if ((bt848_tuner >> 8 == unit ) && 61428679Sbrian ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 61531372Sbrian if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 61628679Sbrian bktr->bt848_tuner = (bt848_tuner & 0xff); 61731372Sbrian probeCard(bktr, FALSE, unit); 61828679Sbrian } 61928679Sbrian } 62028679Sbrian } 62131372Sbrian 62228679Sbrian if (bt848_reverse_mute != -1) { 62331372Sbrian if ((bt848_reverse_mute >> 8) == unit ) { 62426516Sbrian bktr->reverse_mute = bt848_reverse_mute & 0xff; 62528679Sbrian } 62628679Sbrian } 62726516Sbrian 62828679Sbrian if (bt848_slow_msp_audio != -1) { 62928679Sbrian if ((bt848_slow_msp_audio >> 8) == unit ) { 63028679Sbrian bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 63131343Sbrian } 63228679Sbrian } 6336059Samurai 6346059Samurai#ifdef BKTR_NEW_MSP34XX_DRIVER 63530715Sbrian if (bt848_stereo_once != 0) { 63631343Sbrian if ((bt848_stereo_once >> 8) == unit ) { 6376059Samurai bktr->stereo_once = (bt848_stereo_once & 0xff); 63826516Sbrian } 63926516Sbrian } 64028679Sbrian 6416059Samurai if (bt848_amsound != -1) { 64226516Sbrian if ((bt848_amsound >> 8) == unit ) { 64326516Sbrian bktr->amsound = (bt848_amsound & 0xff); 64426516Sbrian } 6456059Samurai } 64625566Sbrian 64726516Sbrian if (bt848_dolby != -1) { 64828679Sbrian if ((bt848_dolby >> 8) == unit ) { 64928679Sbrian bktr->dolby = (bt848_dolby & 0xff); 65026516Sbrian } 6516059Samurai } 6526059Samurai#endif 65328679Sbrian 65426516Sbrian switch ( FUNCTION( minor(dev) ) ) { 65528679Sbrian case VIDEO_DEV: 65628679Sbrian result = video_open( bktr ); 65726516Sbrian break; 6586059Samurai case TUNER_DEV: 6596059Samurai result = tuner_open( bktr ); 6606059Samurai break; 6616059Samurai case VBI_DEV: 6626059Samurai result = vbi_open( bktr ); 6636059Samurai break; 66426516Sbrian default: 6656059Samurai result = ENXIO; 6666059Samurai break; 66730715Sbrian } 66831343Sbrian 6696059Samurai /* If there was an error opening the device, undo the busy status */ 67028679Sbrian if (result != 0) 6716059Samurai device_unbusy(devclass_get_device(bktr_devclass, unit)); 6726059Samurai return( result ); 67331343Sbrian} 6746059Samurai 67531343Sbrian 6766059Samurai/* 67726516Sbrian * 67831343Sbrian */ 67931372Sbrianstatic int 68031343Sbrianbktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 68131343Sbrian{ 68231343Sbrian bktr_ptr_t bktr; 68331343Sbrian int unit; 68431343Sbrian int result; 68526516Sbrian 68626516Sbrian unit = UNIT( minor(dev) ); 68726516Sbrian 68826516Sbrian /* Get the device data */ 68928679Sbrian bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 69026516Sbrian if (bktr == NULL) { 69126516Sbrian /* the device is no longer valid/functioning */ 69226516Sbrian return (ENXIO); 6936059Samurai } 6946059Samurai 69518885Sjkh switch ( FUNCTION( minor(dev) ) ) { 69618885Sjkh case VIDEO_DEV: 6976059Samurai result = video_close( bktr ); 69818885Sjkh break; 6996059Samurai case TUNER_DEV: 70031343Sbrian result = tuner_close( bktr ); 7016735Samurai break; 70231121Sbrian case VBI_DEV: 7036059Samurai result = vbi_close( bktr ); 7046735Samurai break; 70518885Sjkh default: 70626516Sbrian return (ENXIO); 70718885Sjkh break; 70818885Sjkh } 7096735Samurai 71028679Sbrian device_unbusy(devclass_get_device(bktr_devclass, unit)); 7116735Samurai return( result ); 7126735Samurai} 7136735Samurai 7146059Samurai 7156735Samurai/* 7166059Samurai * 7176735Samurai */ 71826516Sbrianstatic int 71926516Sbrianbktr_read( dev_t dev, struct uio *uio, int ioflag ) 7206059Samurai{ 7216059Samurai bktr_ptr_t bktr; 7226059Samurai int unit; 72331121Sbrian 7246059Samurai unit = UNIT(minor(dev)); 72531343Sbrian 7266059Samurai /* Get the device data */ 7276059Samurai bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 7286059Samurai if (bktr == NULL) { 7296059Samurai /* the device is no longer valid/functioning */ 7306059Samurai return (ENXIO); 7316059Samurai } 73231121Sbrian 73331121Sbrian switch ( FUNCTION( minor(dev) ) ) { 73431121Sbrian case VIDEO_DEV: 73531121Sbrian return( video_read( bktr, unit, dev, uio ) ); 73631121Sbrian case VBI_DEV: 7376059Samurai return( vbi_read( bktr, uio, ioflag ) ); 73831121Sbrian } 73931343Sbrian return( ENXIO ); 74031121Sbrian} 74131156Sbrian 74231156Sbrian 74331156Sbrian/* 74431156Sbrian * 74531156Sbrian */ 74631156Sbrianstatic int 74731156Sbrianbktr_write( dev_t dev, struct uio *uio, int ioflag ) 74831156Sbrian{ 74931156Sbrian return( EINVAL ); /* XXX or ENXIO ? */ 75031156Sbrian} 75131156Sbrian 75231156Sbrian 75331156Sbrian/* 75431156Sbrian * 75531156Sbrian */ 75631156Sbrianstatic int 75731156Sbrianbktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 75831156Sbrian{ 75931156Sbrian bktr_ptr_t bktr; 76031121Sbrian int unit; 76131156Sbrian 7626059Samurai unit = UNIT(minor(dev)); 7636059Samurai 76431121Sbrian /* Get the device data */ 76531156Sbrian bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 76631121Sbrian if (bktr == NULL) { 76731121Sbrian /* the device is no longer valid/functioning */ 76831121Sbrian return (ENXIO); 76931121Sbrian } 77031121Sbrian 77131343Sbrian if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 77231121Sbrian return( ENOMEM ); 77331121Sbrian 7746059Samurai switch ( FUNCTION( minor(dev) ) ) { 77531343Sbrian case VIDEO_DEV: 7766059Samurai return( video_ioctl( bktr, unit, cmd, arg, td ) ); 77731343Sbrian case TUNER_DEV: 77831343Sbrian return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 77926516Sbrian } 78031343Sbrian 7816059Samurai return( ENXIO ); 78226516Sbrian} 78326516Sbrian 78426516Sbrian 7856059Samurai/* 7866059Samurai * 7876059Samurai */ 78831343Sbrianstatic int 7896059Samuraibktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 7906059Samurai{ 79126516Sbrian int unit; 79226516Sbrian bktr_ptr_t bktr; 79326516Sbrian 7946059Samurai unit = UNIT(minor(dev)); 79530913Sbrian 79628679Sbrian if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 79731034Sbrian return( -1 ); 79826516Sbrian 79926516Sbrian /* Get the device data */ 80028679Sbrian bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 8016059Samurai if (bktr == NULL) { 80226516Sbrian /* the device is no longer valid/functioning */ 80326516Sbrian return (ENXIO); 80426516Sbrian } 80526516Sbrian 8066059Samurai if (nprot & PROT_EXEC) 80728679Sbrian return( -1 ); 8086059Samurai 8096059Samurai if (offset < 0) 8106059Samurai return( -1 ); 81131343Sbrian 8126059Samurai if (offset >= bktr->alloc_pages * PAGE_SIZE) 81331203Sbrian return( -1 ); 81431203Sbrian 81531203Sbrian *paddr = vtophys(bktr->bigbuf) + offset; 81631203Sbrian return( 0 ); 81731343Sbrian} 81831203Sbrian 81931121Sbrianstatic int 82026516Sbrianbktr_poll( dev_t dev, int events, struct thread *td) 82126516Sbrian{ 8226059Samurai int unit; 8236059Samurai bktr_ptr_t bktr; 8246059Samurai int revents = 0; 82531343Sbrian DECLARE_INTR_MASK(s); 8266059Samurai 82726098Sbrian unit = UNIT(minor(dev)); 8286059Samurai 82926516Sbrian /* Get the device data */ 8306059Samurai bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 8316059Samurai if (bktr == NULL) { 8326059Samurai /* the device is no longer valid/functioning */ 83331343Sbrian return (ENXIO); 8346059Samurai } 8356059Samurai 83626516Sbrian LOCK_VBI(bktr); 8376059Samurai DISABLE_INTR(s); 8386059Samurai 83925067Sbrian if (events & (POLLIN | POLLRDNORM)) { 84031343Sbrian 8416059Samurai switch ( FUNCTION( minor(dev) ) ) { 8426059Samurai case VBI_DEV: 8436059Samurai if(bktr->vbisize == 0) 84431343Sbrian selrecord(td, &bktr->vbi_select); 84531343Sbrian else 8466735Samurai revents |= events & (POLLIN | POLLRDNORM); 84726516Sbrian break; 8486735Samurai } 84931343Sbrian } 8506735Samurai 8516735Samurai ENABLE_INTR(s); 85226516Sbrian UNLOCK_VBI(bktr); 8536059Samurai 85431343Sbrian return (revents); 8556059Samurai} 85626516Sbrian 8576059Samurai#endif /* FreeBSD 4.x specific kernel interface routines */ 8586059Samurai 85925067Sbrian/*****************/ 86031343Sbrian/* *** BSDI *** */ 86111336Samurai/*****************/ 86231343Sbrian 86331343Sbrian#if defined(__bsdi__) 86431343Sbrian#endif /* __bsdi__ BSDI specific kernel interface routines */ 86526516Sbrian 86626516Sbrian 86726516Sbrian/*****************************/ 86825067Sbrian/* *** OpenBSD / NetBSD *** */ 86925067Sbrian/*****************************/ 87025067Sbrian#if defined(__NetBSD__) || defined(__OpenBSD__) 87131343Sbrian 87225067Sbrian#define IPL_VIDEO IPL_BIO /* XXX */ 87311336Samurai 87411336Samuraistatic int bktr_intr(void *arg) { return common_bktr_intr(arg); } 87524939Sbrian 87611336Samurai#define bktr_open bktropen 87731343Sbrian#define bktr_close bktrclose 87831343Sbrian#define bktr_read bktrread 87931343Sbrian#define bktr_write bktrwrite 88011336Samurai#define bktr_ioctl bktrioctl 88130715Sbrian#define bktr_mmap bktrmmap 88226516Sbrian 88331343Sbrianvm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 88411336Samurai vm_offset_t, vm_offset_t); 88526516Sbrian 88611336Samurai#if defined(__OpenBSD__) 88711336Samuraistatic int bktr_probe(struct device *, void *, void *); 88826516Sbrian#else 88928679Sbrianstatic int bktr_probe(struct device *, struct cfdata *, void *); 89011336Samurai#endif 89111336Samuraistatic void bktr_attach(struct device *, struct device *, void *); 89224939Sbrian 89331343Sbrianstruct cfattach bktr_ca = { 89424939Sbrian sizeof(struct bktr_softc), bktr_probe, bktr_attach 89524939Sbrian}; 89628679Sbrian 89730715Sbrian#if defined(__NetBSD__) 89828679Sbrianextern struct cfdriver bktr_cd; 89928679Sbrian#else 90028679Sbrianstruct cfdriver bktr_cd = { 90128679Sbrian NULL, "bktr", DV_DULL 90228679Sbrian}; 90328679Sbrian#endif 90426516Sbrian 90528679Sbrianint 90624939Sbrianbktr_probe(parent, match, aux) 90728679Sbrian struct device *parent; 90828679Sbrian#if defined(__OpenBSD__) 90924939Sbrian void *match; 91031343Sbrian#else 91131343Sbrian struct cfdata *match; 91211336Samurai#endif 91311336Samurai void *aux; 91426516Sbrian{ 91526516Sbrian struct pci_attach_args *pa = aux; 91626516Sbrian 91726516Sbrian if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 91811336Samurai (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 91911336Samurai PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 92026516Sbrian PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 92111336Samurai PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 92226516Sbrian return 1; 92311336Samurai 92411336Samurai return 0; 92525067Sbrian} 92631343Sbrian 92728327Sbrian 92828461Sbrian/* 92928461Sbrian * the attach routine. 93028461Sbrian */ 93131343Sbrianstatic void 93231343Sbrianbktr_attach(struct device *parent, struct device *self, void *aux) 93331343Sbrian{ 93431343Sbrian bktr_ptr_t bktr; 93531343Sbrian u_long latency; 93631343Sbrian u_long fun; 93731343Sbrian unsigned int rev; 93828461Sbrian 93928461Sbrian#if defined(__OpenBSD__) 94028327Sbrian struct pci_attach_args *pa = aux; 94128327Sbrian pci_chipset_tag_t pc = pa->pa_pc; 94228327Sbrian 94328327Sbrian pci_intr_handle_t ih; 94428327Sbrian const char *intrstr; 94531081Sbrian int retval; 94631081Sbrian int unit; 94731081Sbrian 94828327Sbrian bktr = (bktr_ptr_t)self; 94931343Sbrian unit = bktr->bktr_dev.dv_unit; 95026940Sbrian 95126940Sbrian bktr->pc = pa->pa_pc; 95226940Sbrian bktr->tag = pa->pa_tag; 95331343Sbrian bktr->dmat = pa->pa_dmat; 95431081Sbrian 95531081Sbrian /* 95631081Sbrian * map memory 95731343Sbrian */ 95831343Sbrian bktr->memt = pa->pa_memt; 95931343Sbrian retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 96031081Sbrian &bktr->phys_base, &bktr->obmemsz, NULL); 96131343Sbrian if (!retval) 96231081Sbrian retval = bus_space_map(pa->pa_memt, bktr->phys_base, 96331343Sbrian bktr->obmemsz, 0, &bktr->memh); 96431081Sbrian if (retval) { 96531081Sbrian printf(": couldn't map memory\n"); 96631343Sbrian return; 96731343Sbrian } 96831343Sbrian 96931081Sbrian 97031081Sbrian /* 97131081Sbrian * map interrupt 97231081Sbrian */ 97331081Sbrian if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 97431081Sbrian pa->pa_intrline, &ih)) { 97531081Sbrian printf(": couldn't map interrupt\n"); 97631081Sbrian return; 97731081Sbrian } 97831081Sbrian intrstr = pci_intr_string(pa->pa_pc, ih); 97931081Sbrian 98031081Sbrian bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 98131081Sbrian bktr_intr, bktr, bktr->bktr_dev.dv_xname); 98231081Sbrian if (bktr->ih == NULL) { 98331081Sbrian printf(": couldn't establish interrupt"); 98431081Sbrian if (intrstr != NULL) 98531081Sbrian printf(" at %s", intrstr); 98631081Sbrian printf("\n"); 98731081Sbrian return; 98831081Sbrian } 98926940Sbrian 99031081Sbrian if (intrstr != NULL) 99131081Sbrian printf(": %s\n", intrstr); 99226940Sbrian#endif /* __OpenBSD__ */ 99331081Sbrian 99431081Sbrian#if defined(__NetBSD__) 99528679Sbrian struct pci_attach_args *pa = aux; 99631081Sbrian pci_intr_handle_t ih; 99728679Sbrian const char *intrstr; 99828679Sbrian int retval; 99931081Sbrian int unit; 100031081Sbrian 100131081Sbrian bktr = (bktr_ptr_t)self; 100231081Sbrian unit = bktr->bktr_dev.dv_unit; 100331081Sbrian bktr->dmat = pa->pa_dmat; 100431081Sbrian 100531081Sbrian printf("\n"); 100627346Sbrian 100731081Sbrian /* 100828679Sbrian * map memory 100931081Sbrian */ 101031081Sbrian retval = pci_mapreg_map(pa, PCI_MAPREG_START, 101128679Sbrian PCI_MAPREG_TYPE_MEM 101231081Sbrian | PCI_MAPREG_MEM_TYPE_32BIT, 0, 101331081Sbrian &bktr->memt, &bktr->memh, NULL, 101431081Sbrian &bktr->obmemsz); 101531081Sbrian DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 101631081Sbrian bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 101731081Sbrian if (retval) { 101828679Sbrian printf("%s: couldn't map memory\n", bktr_name(bktr)); 101931081Sbrian return; 102027346Sbrian } 102131081Sbrian 102231081Sbrian /* 102327346Sbrian * Disable the brooktree device 102431081Sbrian */ 102526940Sbrian OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 102626940Sbrian OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 102726940Sbrian 102826940Sbrian /* 102926940Sbrian * map interrupt 103031343Sbrian */ 10316059Samurai if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 103231343Sbrian pa->pa_intrline, &ih)) { 10336059Samurai printf("%s: couldn't map interrupt\n", 10346059Samurai bktr_name(bktr)); 10356059Samurai return; 103631343Sbrian } 10376059Samurai intrstr = pci_intr_string(pa->pa_pc, ih); 103826516Sbrian bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 103926516Sbrian bktr_intr, bktr); 104031343Sbrian if (bktr->ih == NULL) { 104131343Sbrian printf("%s: couldn't establish interrupt", 104230913Sbrian bktr_name(bktr)); 104330913Sbrian if (intrstr != NULL) 10446059Samurai printf(" at %s", intrstr); 104531343Sbrian printf("\n"); 104631343Sbrian return; 104726516Sbrian } 104831288Sbrian if (intrstr != NULL) 104930913Sbrian printf("%s: interrupting at %s\n", bktr_name(bktr), 105030913Sbrian intrstr); 105130913Sbrian#endif /* __NetBSD__ */ 105230913Sbrian 105330913Sbrian/* 105430913Sbrian * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 105530913Sbrian * you have more than four, then 16 would probably be a better value. 105630913Sbrian */ 105730913Sbrian#ifndef BROOKTREE_DEF_LATENCY_VALUE 105830913Sbrian#define BROOKTREE_DEF_LATENCY_VALUE 10 105930913Sbrian#endif 106026516Sbrian latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 106131343Sbrian latency = (latency >> 8) & 0xff; 106226516Sbrian 106331343Sbrian if (!latency) { 106426516Sbrian if (bootverbose) { 106531343Sbrian printf("%s: PCI bus latency was 0 changing to %d", 106628679Sbrian bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 106730913Sbrian } 106828679Sbrian latency = BROOKTREE_DEF_LATENCY_VALUE; 106930913Sbrian pci_conf_write(pa->pa_pc, pa->pa_tag, 10706059Samurai PCI_LATENCY_TIMER, latency<<8); 10716059Samurai } 107226516Sbrian 107331343Sbrian 107426516Sbrian /* Enabled Bus Master 10756059Samurai XXX: check if all old DMA is stopped first (e.g. after warm 107626516Sbrian boot) */ 10776059Samurai fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 107826516Sbrian pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 10796059Samurai fun | PCI_COMMAND_MASTER_ENABLE); 10806059Samurai 10816059Samurai /* read the pci id and determine the card type */ 108231343Sbrian fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 10836059Samurai rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 10846059Samurai 108531343Sbrian common_bktr_attach(bktr, unit, fun, rev); 108631343Sbrian} 10876059Samurai 10886059Samurai 10896059Samurai/* 109031343Sbrian * Special Memory Allocation 10916059Samurai */ 10926059Samuraivm_offset_t 10936059Samuraiget_bktr_mem(bktr, dmapp, size) 109428679Sbrian bktr_ptr_t bktr; 10956059Samurai bus_dmamap_t *dmapp; 10966059Samurai unsigned int size; 109726516Sbrian{ 10986059Samurai bus_dma_tag_t dmat = bktr->dmat; 10996059Samurai bus_dma_segment_t seg; 11006059Samurai bus_size_t align; 110131343Sbrian int rseg; 11026059Samurai caddr_t kva; 110326326Sbrian 110431343Sbrian /* 11056059Samurai * Allocate a DMA area 110631343Sbrian */ 110731343Sbrian align = 1 << 24; 110826326Sbrian if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 110926516Sbrian &rseg, BUS_DMA_NOWAIT)) { 11106059Samurai align = PAGE_SIZE; 111126516Sbrian if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 111226516Sbrian &rseg, BUS_DMA_NOWAIT)) { 11136059Samurai printf("%s: Unable to dmamem_alloc of %d bytes\n", 111426516Sbrian bktr_name(bktr), size); 111526516Sbrian return 0; 111626516Sbrian } 111726516Sbrian } 111826516Sbrian if (bus_dmamem_map(dmat, &seg, rseg, size, 11196059Samurai &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 11206059Samurai printf("%s: Unable to dmamem_map of %d bytes\n", 11216059Samurai bktr_name(bktr), size); 112231343Sbrian bus_dmamem_free(dmat, &seg, rseg); 112326326Sbrian return 0; 112426326Sbrian } 112531343Sbrian#ifdef __OpenBSD__ 112626326Sbrian bktr->dm_mapsize = size; 112731343Sbrian#endif 112831343Sbrian /* 112926516Sbrian * Create and locd the DMA map for the DMA area 113026326Sbrian */ 113126516Sbrian if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 113226516Sbrian printf("%s: Unable to dmamap_create of %d bytes\n", 113326516Sbrian bktr_name(bktr), size); 113426326Sbrian bus_dmamem_unmap(dmat, kva, size); 113526516Sbrian bus_dmamem_free(dmat, &seg, rseg); 113626516Sbrian return 0; 113726326Sbrian } 113826516Sbrian if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 113926516Sbrian printf("%s: Unable to dmamap_load of %d bytes\n", 114026516Sbrian bktr_name(bktr), size); 114126516Sbrian bus_dmamem_unmap(dmat, kva, size); 114226516Sbrian bus_dmamem_free(dmat, &seg, rseg); 114326326Sbrian bus_dmamap_destroy(dmat, *dmapp); 114426326Sbrian return 0; 114526326Sbrian } 114631343Sbrian return (vm_offset_t)kva; 11476059Samurai} 114831343Sbrian 114931343Sbrianvoid 115028679Sbrianfree_bktr_mem(bktr, dmap, kva) 115131343Sbrian bktr_ptr_t bktr; 115231343Sbrian bus_dmamap_t dmap; 11536735Samurai vm_offset_t kva; 11546735Samurai{ 115531343Sbrian bus_dma_tag_t dmat = bktr->dmat; 115631343Sbrian 11576735Samurai#ifdef __NetBSD__ 11586735Samurai bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 11596735Samurai#else 11606735Samurai bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 116126516Sbrian#endif 11626059Samurai bus_dmamem_free(dmat, dmap->dm_segs, 1); 116326516Sbrian bus_dmamap_destroy(dmat, dmap); 11646059Samurai} 11656059Samurai 116630715Sbrian 116731343Sbrian/*--------------------------------------------------------- 11686059Samurai** 11696059Samurai** BrookTree 848 character device driver routines 11706059Samurai** 11716059Samurai**--------------------------------------------------------- 11726059Samurai*/ 11736059Samurai 117430715Sbrian 11756059Samurai#define VIDEO_DEV 0x00 11766059Samurai#define TUNER_DEV 0x01 117728679Sbrian#define VBI_DEV 0x02 11786059Samurai 11796059Samurai#define UNIT(x) (minor((x) & 0x0f)) 11806059Samurai#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 118131343Sbrian 11826059Samurai/* 118328394Sbrian * 11846059Samurai */ 118531343Sbrianint 118628679Sbrianbktr_open(dev_t dev, int flags, int fmt, struct thread *td) 118726516Sbrian{ 118828394Sbrian bktr_ptr_t bktr; 118928394Sbrian int unit; 119028394Sbrian 119131343Sbrian unit = UNIT(dev); 119231343Sbrian 119328679Sbrian /* unit out of range */ 119428679Sbrian if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 119528679Sbrian return(ENXIO); 119628679Sbrian 119731343Sbrian bktr = bktr_cd.cd_devs[unit]; 119831343Sbrian 119925630Sbrian if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 120025630Sbrian return(ENXIO); 120125630Sbrian 120228679Sbrian switch (FUNCTION(dev)) { 120331343Sbrian case VIDEO_DEV: 120431343Sbrian return(video_open(bktr)); 120531343Sbrian case TUNER_DEV: 120631343Sbrian return(tuner_open(bktr)); 120728679Sbrian case VBI_DEV: 12089440Samurai return(vbi_open(bktr)); 12096059Samurai } 12106059Samurai 12116059Samurai return(ENXIO); 121228394Sbrian} 12136059Samurai 12146059Samurai 12156059Samurai/* 12166059Samurai * 12176059Samurai */ 12186059Samuraiint 12196059Samuraibktr_close(dev_t dev, int flags, int fmt, struct thread *td) 12206059Samurai{ 12216059Samurai bktr_ptr_t bktr; 12226059Samurai int unit; 12236059Samurai 122428537Sbrian unit = UNIT(dev); 122528537Sbrian 122628537Sbrian bktr = bktr_cd.cd_devs[unit]; 122731121Sbrian 122831121Sbrian switch (FUNCTION(dev)) { 122931121Sbrian case VIDEO_DEV: 123031121Sbrian return(video_close(bktr)); 123126516Sbrian case TUNER_DEV: 12326059Samurai return(tuner_close(bktr)); 12336059Samurai case VBI_DEV: 123426516Sbrian return(vbi_close(bktr)); 12356059Samurai } 123630715Sbrian 123728679Sbrian return(ENXIO); 123828679Sbrian} 123928679Sbrian 124031343Sbrian/* 124118752Sjkh * 124218752Sjkh */ 124318752Sjkhint 124418752Sjkhbktr_read(dev_t dev, struct uio *uio, int ioflag) 124518752Sjkh{ 124618752Sjkh bktr_ptr_t bktr; 124728679Sbrian int unit; 124818752Sjkh 124928679Sbrian unit = UNIT(dev); 125018752Sjkh 125118752Sjkh bktr = bktr_cd.cd_devs[unit]; 125218752Sjkh 125318752Sjkh switch (FUNCTION(dev)) { 125418752Sjkh case VIDEO_DEV: 125528679Sbrian return(video_read(bktr, unit, dev, uio)); 125628679Sbrian case VBI_DEV: 125728679Sbrian return(vbi_read(bktr, uio, ioflag)); 125828679Sbrian } 125928679Sbrian 126028679Sbrian return(ENXIO); 126118752Sjkh} 126218752Sjkh 126318752Sjkh 126418752Sjkh/* 126531343Sbrian * 126618752Sjkh */ 126731343Sbrianint 126826516Sbrianbktr_write(dev_t dev, struct uio *uio, int ioflag) 126918752Sjkh{ 127018752Sjkh /* operation not supported */ 127118752Sjkh return(EOPNOTSUPP); 127231343Sbrian} 127318752Sjkh 127431343Sbrian/* 127526516Sbrian * 127618752Sjkh */ 127718752Sjkhint 127828679Sbrianbktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 127918752Sjkh{ 128029696Sbrian bktr_ptr_t bktr; 128131343Sbrian int unit; 12826059Samurai 12836059Samurai unit = UNIT(dev); 128431343Sbrian 128531343Sbrian bktr = bktr_cd.cd_devs[unit]; 12866059Samurai 128731343Sbrian if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 128831343Sbrian return(ENOMEM); 128926551Sbrian 129031343Sbrian switch (FUNCTION(dev)) { 129126551Sbrian case VIDEO_DEV: 129226551Sbrian return(video_ioctl(bktr, unit, cmd, arg, pr)); 129328679Sbrian case TUNER_DEV: 129431343Sbrian return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 129528679Sbrian } 129628679Sbrian 129728679Sbrian return(ENXIO); 129831343Sbrian} 129928679Sbrian 130028679Sbrian/* 130128679Sbrian * 130231343Sbrian */ 130328679Sbrianpaddr_t 130428679Sbrianbktr_mmap(dev_t dev, off_t offset, int nprot) 130528679Sbrian{ 130631343Sbrian int unit; 130728679Sbrian bktr_ptr_t bktr; 130828679Sbrian 130928679Sbrian unit = UNIT(dev); 131029696Sbrian 131129696Sbrian if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 131231343Sbrian return(-1); 131329696Sbrian 131431343Sbrian bktr = bktr_cd.cd_devs[unit]; 131529696Sbrian 131630715Sbrian if ((vaddr_t)offset < 0) 131729696Sbrian return(-1); 131829696Sbrian 131928679Sbrian if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 132028679Sbrian return(-1); 132131343Sbrian 132228679Sbrian#ifdef __NetBSD__ 132328679Sbrian return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 132428679Sbrian (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 132531343Sbrian#else 132628679Sbrian return(i386_btop(vtophys(bktr->bigbuf) + offset)); 132728679Sbrian#endif 132828679Sbrian} 132931082Sbrian 133028679Sbrian#endif /* __NetBSD__ || __OpenBSD__ */ 133128679Sbrian