bktr_os.c revision 118819
1/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 118819 2003-08-12 09:45:34Z alex $ */ 2 3/* 4 * This is part of the Driver for Video Capture Cards (Frame grabbers) 5 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 6 * chipset. 7 * Copyright Roger Hardiman and Amancio Hasty. 8 * 9 * bktr_os : This has all the Operating System dependant code, 10 * probe/attach and open/close/ioctl/read/mmap 11 * memory allocation 12 * PCI bus interfacing 13 * 14 * 15 */ 16 17/* 18 * 1. Redistributions of source code must retain the 19 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * This product includes software developed by Amancio Hasty and 33 * Roger Hardiman 34 * 4. The name of the author may not be used to endorse or promote products 35 * derived from this software without specific prior written permission. 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 38 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 41 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 43 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 46 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 47 * POSSIBILITY OF SUCH DAMAGE. 48 */ 49 50 51#include "opt_bktr.h" /* include any kernel config options */ 52 53#define FIFO_RISC_DISABLED 0 54#define ALL_INTS_DISABLED 0 55 56 57/*******************/ 58/* *** FreeBSD *** */ 59/*******************/ 60#ifdef __FreeBSD__ 61 62#include <sys/param.h> 63#include <sys/systm.h> 64#include <sys/conf.h> 65#include <sys/uio.h> 66#include <sys/kernel.h> 67#include <sys/signalvar.h> 68#include <sys/mman.h> 69#include <sys/poll.h> 70#if __FreeBSD_version >= 500014 71#include <sys/selinfo.h> 72#else 73#include <sys/select.h> 74#endif 75#include <sys/vnode.h> 76 77#include <vm/vm.h> 78#include <vm/vm_kern.h> 79#include <vm/pmap.h> 80#include <vm/vm_extern.h> 81 82#if (__FreeBSD_version >=400000) 83#include <sys/bus.h> /* used by smbus and newbus */ 84#endif 85 86#if (__FreeBSD_version >=300000) 87#include <machine/bus_memio.h> /* used by bus space */ 88#include <machine/bus.h> /* used by bus space and newbus */ 89#include <sys/bus.h> 90#endif 91 92#if (__FreeBSD_version >=400000) 93#include <sys/rman.h> /* used by newbus */ 94#include <machine/resource.h> /* used by newbus */ 95#endif 96 97#if (__FreeBSD_version < 500000) 98#include <machine/clock.h> /* for DELAY */ 99#endif 100 101#include <pci/pcivar.h> 102#include <pci/pcireg.h> 103 104#include <sys/sysctl.h> 105int bt848_card = -1; 106int bt848_tuner = -1; 107int bt848_reverse_mute = -1; 108int bt848_format = -1; 109int bt848_slow_msp_audio = -1; 110#ifdef BKTR_NEW_MSP34XX_DRIVER 111int bt848_stereo_once = 0; /* no continuous stereo monitoring */ 112int bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 113 the autoscan seems work well only with FM... */ 114int bt848_dolby = 0; 115#endif 116 117SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 118SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 119SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 120SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 121SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 122SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 123#ifdef BKTR_NEW_MSP34XX_DRIVER 124SYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 125SYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 126SYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 127#endif 128 129#endif /* end freebsd section */ 130 131 132 133/****************/ 134/* *** BSDI *** */ 135/****************/ 136#ifdef __bsdi__ 137#endif /* __bsdi__ */ 138 139 140/**************************/ 141/* *** OpenBSD/NetBSD *** */ 142/**************************/ 143#if defined(__NetBSD__) || defined(__OpenBSD__) 144 145#include <sys/param.h> 146#include <sys/systm.h> 147#include <sys/conf.h> 148#include <sys/uio.h> 149#include <sys/kernel.h> 150#include <sys/signalvar.h> 151#include <sys/mman.h> 152#include <sys/poll.h> 153#include <sys/select.h> 154#include <sys/vnode.h> 155 156#include <vm/vm.h> 157 158#ifndef __NetBSD__ 159#include <vm/vm_kern.h> 160#include <vm/pmap.h> 161#include <vm/vm_extern.h> 162#endif 163 164#include <sys/device.h> 165#include <dev/pci/pcivar.h> 166#include <dev/pci/pcireg.h> 167#include <dev/pci/pcidevs.h> 168 169#define BKTR_DEBUG 170#ifdef BKTR_DEBUG 171int bktr_debug = 0; 172#define DPR(x) (bktr_debug ? printf x : 0) 173#else 174#define DPR(x) 175#endif 176#endif /* __NetBSD__ || __OpenBSD__ */ 177 178 179#ifdef __NetBSD__ 180#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 181#include <dev/pci/bktr/bktr_reg.h> 182#include <dev/pci/bktr/bktr_tuner.h> 183#include <dev/pci/bktr/bktr_card.h> 184#include <dev/pci/bktr/bktr_audio.h> 185#include <dev/pci/bktr/bktr_core.h> 186#include <dev/pci/bktr/bktr_os.h> 187#else /* Traditional location for .h files */ 188#include <machine/ioctl_meteor.h> 189#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 190#include <dev/bktr/bktr_reg.h> 191#include <dev/bktr/bktr_tuner.h> 192#include <dev/bktr/bktr_card.h> 193#include <dev/bktr/bktr_audio.h> 194#include <dev/bktr/bktr_core.h> 195#include <dev/bktr/bktr_os.h> 196 197#if defined(BKTR_USE_FREEBSD_SMBUS) 198#include <dev/bktr/bktr_i2c.h> 199 200#include "iicbb_if.h" 201#include "smbus_if.h" 202#endif 203#endif 204 205 206/****************************/ 207/* *** FreeBSD 4.x code *** */ 208/****************************/ 209#if (__FreeBSD_version >= 400000) 210 211static int bktr_probe( device_t dev ); 212static int bktr_attach( device_t dev ); 213static int bktr_detach( device_t dev ); 214static int bktr_shutdown( device_t dev ); 215static void bktr_intr(void *arg) { common_bktr_intr(arg); } 216 217static device_method_t bktr_methods[] = { 218 /* Device interface */ 219 DEVMETHOD(device_probe, bktr_probe), 220 DEVMETHOD(device_attach, bktr_attach), 221 DEVMETHOD(device_detach, bktr_detach), 222 DEVMETHOD(device_shutdown, bktr_shutdown), 223 224#if defined(BKTR_USE_FREEBSD_SMBUS) 225 /* iicbb interface */ 226 DEVMETHOD(iicbb_callback, bti2c_iic_callback), 227 DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 228 DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 229 DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 230 DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 231 DEVMETHOD(iicbb_reset, bti2c_iic_reset), 232 233 /* smbus interface */ 234 DEVMETHOD(smbus_callback, bti2c_smb_callback), 235 DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 236 DEVMETHOD(smbus_writew, bti2c_smb_writew), 237 DEVMETHOD(smbus_readb, bti2c_smb_readb), 238#endif 239 240 { 0, 0 } 241}; 242 243static driver_t bktr_driver = { 244 "bktr", 245 bktr_methods, 246 sizeof(struct bktr_softc), 247}; 248 249static devclass_t bktr_devclass; 250 251static d_open_t bktr_open; 252static d_close_t bktr_close; 253static d_read_t bktr_read; 254static d_write_t bktr_write; 255static d_ioctl_t bktr_ioctl; 256static d_mmap_t bktr_mmap; 257static d_poll_t bktr_poll; 258 259#define CDEV_MAJOR 92 260static struct cdevsw bktr_cdevsw = { 261 .d_open = bktr_open, 262 .d_close = bktr_close, 263 .d_read = bktr_read, 264 .d_write = bktr_write, 265 .d_ioctl = bktr_ioctl, 266 .d_poll = bktr_poll, 267 .d_mmap = bktr_mmap, 268 .d_name = "bktr", 269 .d_maj = CDEV_MAJOR, 270}; 271 272DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 273#if (__FreeBSD_version > 410000) 274MODULE_DEPEND(bktr, bktr_mem, 1,1,1); 275MODULE_VERSION(bktr, 1); 276#endif 277 278 279/* 280 * the boot time probe routine. 281 */ 282static int 283bktr_probe( device_t dev ) 284{ 285 unsigned int type = pci_get_devid(dev); 286 unsigned int rev = pci_get_revid(dev); 287 288 if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 289 { 290 switch (PCI_PRODUCT(type)) { 291 case PCI_PRODUCT_BROOKTREE_BT848: 292 if (rev == 0x12) 293 device_set_desc(dev, "BrookTree 848A"); 294 else 295 device_set_desc(dev, "BrookTree 848"); 296 return 0; 297 case PCI_PRODUCT_BROOKTREE_BT849: 298 device_set_desc(dev, "BrookTree 849A"); 299 return 0; 300 case PCI_PRODUCT_BROOKTREE_BT878: 301 device_set_desc(dev, "BrookTree 878"); 302 return 0; 303 case PCI_PRODUCT_BROOKTREE_BT879: 304 device_set_desc(dev, "BrookTree 879"); 305 return 0; 306 } 307 }; 308 309 return ENXIO; 310} 311 312 313/* 314 * the attach routine. 315 */ 316static int 317bktr_attach( device_t dev ) 318{ 319 u_long latency; 320 u_long fun; 321 u_long val; 322 unsigned int rev; 323 unsigned int unit; 324 int error = 0; 325#ifdef BROOKTREE_IRQ 326 u_long old_irq, new_irq; 327#endif 328 329 struct bktr_softc *bktr = device_get_softc(dev); 330 331 unit = device_get_unit(dev); 332 333 /* build the device name for bktr_name() */ 334 snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 335 336 /* 337 * Enable bus mastering and Memory Mapped device 338 */ 339 val = pci_read_config(dev, PCIR_COMMAND, 4); 340 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 341 pci_write_config(dev, PCIR_COMMAND, val, 4); 342 343 /* 344 * Map control/status registers. 345 */ 346 bktr->mem_rid = PCIR_MAPS; 347 bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &bktr->mem_rid, 348 0, ~0, 1, RF_ACTIVE); 349 350 351 if (!bktr->res_mem) { 352 device_printf(dev, "could not map memory\n"); 353 error = ENXIO; 354 goto fail; 355 } 356 bktr->memt = rman_get_bustag(bktr->res_mem); 357 bktr->memh = rman_get_bushandle(bktr->res_mem); 358 359 360 /* 361 * Disable the brooktree device 362 */ 363 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 364 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 365 366 367#ifdef BROOKTREE_IRQ /* from the configuration file */ 368 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 369 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 370 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 371 printf("bktr%d: attach: irq changed from %d to %d\n", 372 unit, (old_irq & 0xff), (new_irq & 0xff)); 373#endif 374 375 /* 376 * Allocate our interrupt. 377 */ 378 bktr->irq_rid = 0; 379 bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &bktr->irq_rid, 380 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 381 if (bktr->res_irq == NULL) { 382 device_printf(dev, "could not map interrupt\n"); 383 error = ENXIO; 384 goto fail; 385 } 386 387 error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 388 bktr_intr, bktr, &bktr->res_ih); 389 if (error) { 390 device_printf(dev, "could not setup irq\n"); 391 goto fail; 392 393 } 394 395 396 /* Update the Device Control Register */ 397 /* on Bt878 and Bt879 cards */ 398 fun = pci_read_config( dev, 0x40, 2); 399 fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 400 401#if defined( BKTR_430_FX_MODE ) 402 if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 403 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 404#endif 405 406#if defined( BKTR_SIS_VIA_MODE ) 407 if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 408 fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 409 OPTi chipset motherboards too */ 410#endif 411 pci_write_config(dev, 0x40, fun, 2); 412 413#if defined(BKTR_USE_FREEBSD_SMBUS) 414 if (bt848_i2c_attach(dev)) 415 printf("bktr%d: i2c_attach: can't attach\n", unit); 416#endif 417 418/* 419 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 420 * you have more than four, then 16 would probably be a better value. 421 */ 422#ifndef BROOKTREE_DEF_LATENCY_VALUE 423#define BROOKTREE_DEF_LATENCY_VALUE 10 424#endif 425 latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 426 latency = (latency >> 8) & 0xff; 427 if ( bootverbose ) { 428 if (latency) 429 printf("brooktree%d: PCI bus latency is", unit); 430 else 431 printf("brooktree%d: PCI bus latency was 0 changing to", 432 unit); 433 } 434 if ( !latency ) { 435 latency = BROOKTREE_DEF_LATENCY_VALUE; 436 pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 437 } 438 if ( bootverbose ) { 439 printf(" %d.\n", (int) latency); 440 } 441 442 /* read the pci device id and revision id */ 443 fun = pci_get_devid(dev); 444 rev = pci_get_revid(dev); 445 446 /* call the common attach code */ 447 common_bktr_attach( bktr, unit, fun, rev ); 448 449 /* make the device entries */ 450 bktr->bktrdev = make_dev(&bktr_cdevsw, unit, 451 0, 0, 0444, "bktr%d", unit); 452 bktr->tunerdev= make_dev(&bktr_cdevsw, unit+16, 453 0, 0, 0444, "tuner%d", unit); 454 bktr->vbidev = make_dev(&bktr_cdevsw, unit+32, 455 0, 0, 0444, "vbi%d" , unit); 456 457 458 /* if this is unit 0 (/dev/bktr0, /dev/tuner0, /dev/vbi0) then make */ 459 /* alias entries to /dev/bktr /dev/tuner and /dev/vbi */ 460#if (__FreeBSD_version >=500000) 461 if (unit == 0) { 462 bktr->bktrdev_alias = make_dev_alias(bktr->bktrdev, "bktr"); 463 bktr->tunerdev_alias= make_dev_alias(bktr->tunerdev, "tuner"); 464 bktr->vbidev_alias = make_dev_alias(bktr->vbidev, "vbi"); 465 } 466#endif 467 468 return 0; 469 470fail: 471 if (bktr->res_irq) 472 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 473 if (bktr->res_mem) 474 bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 475 return error; 476 477} 478 479/* 480 * the detach routine. 481 */ 482static int 483bktr_detach( device_t dev ) 484{ 485 struct bktr_softc *bktr = device_get_softc(dev); 486 487#ifdef BKTR_NEW_MSP34XX_DRIVER 488 /* Disable the soundchip and kernel thread */ 489 if (bktr->msp3400c_info != NULL) 490 msp_detach(bktr); 491#endif 492 493 /* Disable the brooktree device */ 494 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 495 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 496 497#if defined(BKTR_USE_FREEBSD_SMBUS) 498 if (bt848_i2c_detach(dev)) 499 printf("bktr%d: i2c_attach: can't attach\n", 500 device_get_unit(dev)); 501#endif 502 503 /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 504 /* The memory is retained by the bktr_mem module so we can unload and */ 505 /* then reload the main bktr driver module */ 506 507 /* Unregister the /dev/bktrN, tunerN and vbiN devices, 508 * the aliases for unit 0 are automatically destroyed */ 509 destroy_dev(bktr->vbidev); 510 destroy_dev(bktr->tunerdev); 511 destroy_dev(bktr->bktrdev); 512 513 /* 514 * Deallocate resources. 515 */ 516 bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 517 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 518 bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 519 520 return 0; 521} 522 523/* 524 * the shutdown routine. 525 */ 526static int 527bktr_shutdown( device_t dev ) 528{ 529 struct bktr_softc *bktr = device_get_softc(dev); 530 531 /* Disable the brooktree device */ 532 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 533 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 534 535 return 0; 536} 537 538 539/* 540 * Special Memory Allocation 541 */ 542vm_offset_t 543get_bktr_mem( int unit, unsigned size ) 544{ 545 vm_offset_t addr = 0; 546 547 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 548 if (addr == 0) 549 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 550 if (addr == 0) { 551 printf("bktr%d: Unable to allocate %d bytes of memory.\n", 552 unit, size); 553 } 554 555 return( addr ); 556} 557 558 559/*--------------------------------------------------------- 560** 561** BrookTree 848 character device driver routines 562** 563**--------------------------------------------------------- 564*/ 565 566#define VIDEO_DEV 0x00 567#define TUNER_DEV 0x01 568#define VBI_DEV 0x02 569 570#define UNIT(x) ((x) & 0x0f) 571#define FUNCTION(x) (x >> 4) 572 573/* 574 * 575 */ 576static int 577bktr_open( dev_t dev, int flags, int fmt, struct thread *td ) 578{ 579 bktr_ptr_t bktr; 580 int unit; 581 int result; 582 583 unit = UNIT( minor(dev) ); 584 585 /* Get the device data */ 586 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 587 if (bktr == NULL) { 588 /* the device is no longer valid/functioning */ 589 return (ENXIO); 590 } 591 592 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 593 return( ENXIO ); 594 595 /* Record that the device is now busy */ 596 device_busy(devclass_get_device(bktr_devclass, unit)); 597 598 599 if (bt848_card != -1) { 600 if ((bt848_card >> 8 == unit ) && 601 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 602 if ( bktr->bt848_card != (bt848_card & 0xff) ) { 603 bktr->bt848_card = (bt848_card & 0xff); 604 probeCard(bktr, FALSE, unit); 605 } 606 } 607 } 608 609 if (bt848_tuner != -1) { 610 if ((bt848_tuner >> 8 == unit ) && 611 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 612 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 613 bktr->bt848_tuner = (bt848_tuner & 0xff); 614 probeCard(bktr, FALSE, unit); 615 } 616 } 617 } 618 619 if (bt848_reverse_mute != -1) { 620 if ((bt848_reverse_mute >> 8) == unit ) { 621 bktr->reverse_mute = bt848_reverse_mute & 0xff; 622 } 623 } 624 625 if (bt848_slow_msp_audio != -1) { 626 if ((bt848_slow_msp_audio >> 8) == unit ) { 627 bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 628 } 629 } 630 631#ifdef BKTR_NEW_MSP34XX_DRIVER 632 if (bt848_stereo_once != 0) { 633 if ((bt848_stereo_once >> 8) == unit ) { 634 bktr->stereo_once = (bt848_stereo_once & 0xff); 635 } 636 } 637 638 if (bt848_amsound != -1) { 639 if ((bt848_amsound >> 8) == unit ) { 640 bktr->amsound = (bt848_amsound & 0xff); 641 } 642 } 643 644 if (bt848_dolby != -1) { 645 if ((bt848_dolby >> 8) == unit ) { 646 bktr->dolby = (bt848_dolby & 0xff); 647 } 648 } 649#endif 650 651 switch ( FUNCTION( minor(dev) ) ) { 652 case VIDEO_DEV: 653 result = video_open( bktr ); 654 break; 655 case TUNER_DEV: 656 result = tuner_open( bktr ); 657 break; 658 case VBI_DEV: 659 result = vbi_open( bktr ); 660 break; 661 default: 662 result = ENXIO; 663 break; 664 } 665 666 /* If there was an error opening the device, undo the busy status */ 667 if (result != 0) 668 device_unbusy(devclass_get_device(bktr_devclass, unit)); 669 return( result ); 670} 671 672 673/* 674 * 675 */ 676static int 677bktr_close( dev_t dev, int flags, int fmt, struct thread *td ) 678{ 679 bktr_ptr_t bktr; 680 int unit; 681 int result; 682 683 unit = UNIT( minor(dev) ); 684 685 /* Get the device data */ 686 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 687 if (bktr == NULL) { 688 /* the device is no longer valid/functioning */ 689 return (ENXIO); 690 } 691 692 switch ( FUNCTION( minor(dev) ) ) { 693 case VIDEO_DEV: 694 result = video_close( bktr ); 695 break; 696 case TUNER_DEV: 697 result = tuner_close( bktr ); 698 break; 699 case VBI_DEV: 700 result = vbi_close( bktr ); 701 break; 702 default: 703 return (ENXIO); 704 break; 705 } 706 707 device_unbusy(devclass_get_device(bktr_devclass, unit)); 708 return( result ); 709} 710 711 712/* 713 * 714 */ 715static int 716bktr_read( dev_t dev, struct uio *uio, int ioflag ) 717{ 718 bktr_ptr_t bktr; 719 int unit; 720 721 unit = UNIT(minor(dev)); 722 723 /* Get the device data */ 724 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 725 if (bktr == NULL) { 726 /* the device is no longer valid/functioning */ 727 return (ENXIO); 728 } 729 730 switch ( FUNCTION( minor(dev) ) ) { 731 case VIDEO_DEV: 732 return( video_read( bktr, unit, dev, uio ) ); 733 case VBI_DEV: 734 return( vbi_read( bktr, uio, ioflag ) ); 735 } 736 return( ENXIO ); 737} 738 739 740/* 741 * 742 */ 743static int 744bktr_write( dev_t dev, struct uio *uio, int ioflag ) 745{ 746 return( EINVAL ); /* XXX or ENXIO ? */ 747} 748 749 750/* 751 * 752 */ 753static int 754bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td ) 755{ 756 bktr_ptr_t bktr; 757 int unit; 758 759 unit = UNIT(minor(dev)); 760 761 /* Get the device data */ 762 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 763 if (bktr == NULL) { 764 /* the device is no longer valid/functioning */ 765 return (ENXIO); 766 } 767 768 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 769 return( ENOMEM ); 770 771 switch ( FUNCTION( minor(dev) ) ) { 772 case VIDEO_DEV: 773 return( video_ioctl( bktr, unit, cmd, arg, td ) ); 774 case TUNER_DEV: 775 return( tuner_ioctl( bktr, unit, cmd, arg, td ) ); 776 } 777 778 return( ENXIO ); 779} 780 781 782/* 783 * 784 */ 785static int 786bktr_mmap( dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot ) 787{ 788 int unit; 789 bktr_ptr_t bktr; 790 791 unit = UNIT(minor(dev)); 792 793 if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 794 return( -1 ); 795 796 /* Get the device data */ 797 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 798 if (bktr == NULL) { 799 /* the device is no longer valid/functioning */ 800 return (ENXIO); 801 } 802 803 if (nprot & PROT_EXEC) 804 return( -1 ); 805 806 if (offset < 0) 807 return( -1 ); 808 809 if (offset >= bktr->alloc_pages * PAGE_SIZE) 810 return( -1 ); 811 812 *paddr = vtophys(bktr->bigbuf) + offset; 813 return( 0 ); 814} 815 816static int 817bktr_poll( dev_t dev, int events, struct thread *td) 818{ 819 int unit; 820 bktr_ptr_t bktr; 821 int revents = 0; 822 DECLARE_INTR_MASK(s); 823 824 unit = UNIT(minor(dev)); 825 826 /* Get the device data */ 827 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 828 if (bktr == NULL) { 829 /* the device is no longer valid/functioning */ 830 return (ENXIO); 831 } 832 833 DISABLE_INTR(s); 834 835 if (events & (POLLIN | POLLRDNORM)) { 836 837 switch ( FUNCTION( minor(dev) ) ) { 838 case VBI_DEV: 839 if(bktr->vbisize == 0) 840 selrecord(td, &bktr->vbi_select); 841 else 842 revents |= events & (POLLIN | POLLRDNORM); 843 break; 844 } 845 } 846 847 ENABLE_INTR(s); 848 849 return (revents); 850} 851 852#endif /* FreeBSD 4.x specific kernel interface routines */ 853 854/*****************/ 855/* *** BSDI *** */ 856/*****************/ 857 858#if defined(__bsdi__) 859#endif /* __bsdi__ BSDI specific kernel interface routines */ 860 861 862/*****************************/ 863/* *** OpenBSD / NetBSD *** */ 864/*****************************/ 865#if defined(__NetBSD__) || defined(__OpenBSD__) 866 867#define IPL_VIDEO IPL_BIO /* XXX */ 868 869static int bktr_intr(void *arg) { return common_bktr_intr(arg); } 870 871#define bktr_open bktropen 872#define bktr_close bktrclose 873#define bktr_read bktrread 874#define bktr_write bktrwrite 875#define bktr_ioctl bktrioctl 876#define bktr_mmap bktrmmap 877 878vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 879 vm_offset_t, vm_offset_t); 880 881#if defined(__OpenBSD__) 882static int bktr_probe(struct device *, void *, void *); 883#else 884static int bktr_probe(struct device *, struct cfdata *, void *); 885#endif 886static void bktr_attach(struct device *, struct device *, void *); 887 888struct cfattach bktr_ca = { 889 sizeof(struct bktr_softc), bktr_probe, bktr_attach 890}; 891 892#if defined(__NetBSD__) 893extern struct cfdriver bktr_cd; 894#else 895struct cfdriver bktr_cd = { 896 NULL, "bktr", DV_DULL 897}; 898#endif 899 900int 901bktr_probe(parent, match, aux) 902 struct device *parent; 903#if defined(__OpenBSD__) 904 void *match; 905#else 906 struct cfdata *match; 907#endif 908 void *aux; 909{ 910 struct pci_attach_args *pa = aux; 911 912 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 913 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 914 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 915 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 916 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 917 return 1; 918 919 return 0; 920} 921 922 923/* 924 * the attach routine. 925 */ 926static void 927bktr_attach(struct device *parent, struct device *self, void *aux) 928{ 929 bktr_ptr_t bktr; 930 u_long latency; 931 u_long fun; 932 unsigned int rev; 933 934#if defined(__OpenBSD__) 935 struct pci_attach_args *pa = aux; 936 pci_chipset_tag_t pc = pa->pa_pc; 937 938 pci_intr_handle_t ih; 939 const char *intrstr; 940 int retval; 941 int unit; 942 943 bktr = (bktr_ptr_t)self; 944 unit = bktr->bktr_dev.dv_unit; 945 946 bktr->pc = pa->pa_pc; 947 bktr->tag = pa->pa_tag; 948 bktr->dmat = pa->pa_dmat; 949 950 /* 951 * map memory 952 */ 953 bktr->memt = pa->pa_memt; 954 retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 955 &bktr->phys_base, &bktr->obmemsz, NULL); 956 if (!retval) 957 retval = bus_space_map(pa->pa_memt, bktr->phys_base, 958 bktr->obmemsz, 0, &bktr->memh); 959 if (retval) { 960 printf(": couldn't map memory\n"); 961 return; 962 } 963 964 965 /* 966 * map interrupt 967 */ 968 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 969 pa->pa_intrline, &ih)) { 970 printf(": couldn't map interrupt\n"); 971 return; 972 } 973 intrstr = pci_intr_string(pa->pa_pc, ih); 974 975 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 976 bktr_intr, bktr, bktr->bktr_dev.dv_xname); 977 if (bktr->ih == NULL) { 978 printf(": couldn't establish interrupt"); 979 if (intrstr != NULL) 980 printf(" at %s", intrstr); 981 printf("\n"); 982 return; 983 } 984 985 if (intrstr != NULL) 986 printf(": %s\n", intrstr); 987#endif /* __OpenBSD__ */ 988 989#if defined(__NetBSD__) 990 struct pci_attach_args *pa = aux; 991 pci_intr_handle_t ih; 992 const char *intrstr; 993 int retval; 994 int unit; 995 996 bktr = (bktr_ptr_t)self; 997 unit = bktr->bktr_dev.dv_unit; 998 bktr->dmat = pa->pa_dmat; 999 1000 printf("\n"); 1001 1002 /* 1003 * map memory 1004 */ 1005 retval = pci_mapreg_map(pa, PCI_MAPREG_START, 1006 PCI_MAPREG_TYPE_MEM 1007 | PCI_MAPREG_MEM_TYPE_32BIT, 0, 1008 &bktr->memt, &bktr->memh, NULL, 1009 &bktr->obmemsz); 1010 DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 1011 bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 1012 if (retval) { 1013 printf("%s: couldn't map memory\n", bktr_name(bktr)); 1014 return; 1015 } 1016 1017 /* 1018 * Disable the brooktree device 1019 */ 1020 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 1021 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 1022 1023 /* 1024 * map interrupt 1025 */ 1026 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 1027 pa->pa_intrline, &ih)) { 1028 printf("%s: couldn't map interrupt\n", 1029 bktr_name(bktr)); 1030 return; 1031 } 1032 intrstr = pci_intr_string(pa->pa_pc, ih); 1033 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 1034 bktr_intr, bktr); 1035 if (bktr->ih == NULL) { 1036 printf("%s: couldn't establish interrupt", 1037 bktr_name(bktr)); 1038 if (intrstr != NULL) 1039 printf(" at %s", intrstr); 1040 printf("\n"); 1041 return; 1042 } 1043 if (intrstr != NULL) 1044 printf("%s: interrupting at %s\n", bktr_name(bktr), 1045 intrstr); 1046#endif /* __NetBSD__ */ 1047 1048/* 1049 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 1050 * you have more than four, then 16 would probably be a better value. 1051 */ 1052#ifndef BROOKTREE_DEF_LATENCY_VALUE 1053#define BROOKTREE_DEF_LATENCY_VALUE 10 1054#endif 1055 latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 1056 latency = (latency >> 8) & 0xff; 1057 1058 if (!latency) { 1059 if (bootverbose) { 1060 printf("%s: PCI bus latency was 0 changing to %d", 1061 bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 1062 } 1063 latency = BROOKTREE_DEF_LATENCY_VALUE; 1064 pci_conf_write(pa->pa_pc, pa->pa_tag, 1065 PCI_LATENCY_TIMER, latency<<8); 1066 } 1067 1068 1069 /* Enabled Bus Master 1070 XXX: check if all old DMA is stopped first (e.g. after warm 1071 boot) */ 1072 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1073 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 1074 fun | PCI_COMMAND_MASTER_ENABLE); 1075 1076 /* read the pci id and determine the card type */ 1077 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 1078 rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 1079 1080 common_bktr_attach(bktr, unit, fun, rev); 1081} 1082 1083 1084/* 1085 * Special Memory Allocation 1086 */ 1087vm_offset_t 1088get_bktr_mem(bktr, dmapp, size) 1089 bktr_ptr_t bktr; 1090 bus_dmamap_t *dmapp; 1091 unsigned int size; 1092{ 1093 bus_dma_tag_t dmat = bktr->dmat; 1094 bus_dma_segment_t seg; 1095 bus_size_t align; 1096 int rseg; 1097 caddr_t kva; 1098 1099 /* 1100 * Allocate a DMA area 1101 */ 1102 align = 1 << 24; 1103 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1104 &rseg, BUS_DMA_NOWAIT)) { 1105 align = PAGE_SIZE; 1106 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1107 &rseg, BUS_DMA_NOWAIT)) { 1108 printf("%s: Unable to dmamem_alloc of %d bytes\n", 1109 bktr_name(bktr), size); 1110 return 0; 1111 } 1112 } 1113 if (bus_dmamem_map(dmat, &seg, rseg, size, 1114 &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 1115 printf("%s: Unable to dmamem_map of %d bytes\n", 1116 bktr_name(bktr), size); 1117 bus_dmamem_free(dmat, &seg, rseg); 1118 return 0; 1119 } 1120#ifdef __OpenBSD__ 1121 bktr->dm_mapsize = size; 1122#endif 1123 /* 1124 * Create and locd the DMA map for the DMA area 1125 */ 1126 if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 1127 printf("%s: Unable to dmamap_create of %d bytes\n", 1128 bktr_name(bktr), size); 1129 bus_dmamem_unmap(dmat, kva, size); 1130 bus_dmamem_free(dmat, &seg, rseg); 1131 return 0; 1132 } 1133 if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 1134 printf("%s: Unable to dmamap_load of %d bytes\n", 1135 bktr_name(bktr), size); 1136 bus_dmamem_unmap(dmat, kva, size); 1137 bus_dmamem_free(dmat, &seg, rseg); 1138 bus_dmamap_destroy(dmat, *dmapp); 1139 return 0; 1140 } 1141 return (vm_offset_t)kva; 1142} 1143 1144void 1145free_bktr_mem(bktr, dmap, kva) 1146 bktr_ptr_t bktr; 1147 bus_dmamap_t dmap; 1148 vm_offset_t kva; 1149{ 1150 bus_dma_tag_t dmat = bktr->dmat; 1151 1152#ifdef __NetBSD__ 1153 bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 1154#else 1155 bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 1156#endif 1157 bus_dmamem_free(dmat, dmap->dm_segs, 1); 1158 bus_dmamap_destroy(dmat, dmap); 1159} 1160 1161 1162/*--------------------------------------------------------- 1163** 1164** BrookTree 848 character device driver routines 1165** 1166**--------------------------------------------------------- 1167*/ 1168 1169 1170#define VIDEO_DEV 0x00 1171#define TUNER_DEV 0x01 1172#define VBI_DEV 0x02 1173 1174#define UNIT(x) (minor((x) & 0x0f)) 1175#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 1176 1177/* 1178 * 1179 */ 1180int 1181bktr_open(dev_t dev, int flags, int fmt, struct thread *td) 1182{ 1183 bktr_ptr_t bktr; 1184 int unit; 1185 1186 unit = UNIT(dev); 1187 1188 /* unit out of range */ 1189 if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 1190 return(ENXIO); 1191 1192 bktr = bktr_cd.cd_devs[unit]; 1193 1194 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 1195 return(ENXIO); 1196 1197 switch (FUNCTION(dev)) { 1198 case VIDEO_DEV: 1199 return(video_open(bktr)); 1200 case TUNER_DEV: 1201 return(tuner_open(bktr)); 1202 case VBI_DEV: 1203 return(vbi_open(bktr)); 1204 } 1205 1206 return(ENXIO); 1207} 1208 1209 1210/* 1211 * 1212 */ 1213int 1214bktr_close(dev_t dev, int flags, int fmt, struct thread *td) 1215{ 1216 bktr_ptr_t bktr; 1217 int unit; 1218 1219 unit = UNIT(dev); 1220 1221 bktr = bktr_cd.cd_devs[unit]; 1222 1223 switch (FUNCTION(dev)) { 1224 case VIDEO_DEV: 1225 return(video_close(bktr)); 1226 case TUNER_DEV: 1227 return(tuner_close(bktr)); 1228 case VBI_DEV: 1229 return(vbi_close(bktr)); 1230 } 1231 1232 return(ENXIO); 1233} 1234 1235/* 1236 * 1237 */ 1238int 1239bktr_read(dev_t dev, struct uio *uio, int ioflag) 1240{ 1241 bktr_ptr_t bktr; 1242 int unit; 1243 1244 unit = UNIT(dev); 1245 1246 bktr = bktr_cd.cd_devs[unit]; 1247 1248 switch (FUNCTION(dev)) { 1249 case VIDEO_DEV: 1250 return(video_read(bktr, unit, dev, uio)); 1251 case VBI_DEV: 1252 return(vbi_read(bktr, uio, ioflag)); 1253 } 1254 1255 return(ENXIO); 1256} 1257 1258 1259/* 1260 * 1261 */ 1262int 1263bktr_write(dev_t dev, struct uio *uio, int ioflag) 1264{ 1265 /* operation not supported */ 1266 return(EOPNOTSUPP); 1267} 1268 1269/* 1270 * 1271 */ 1272int 1273bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct thread *td) 1274{ 1275 bktr_ptr_t bktr; 1276 int unit; 1277 1278 unit = UNIT(dev); 1279 1280 bktr = bktr_cd.cd_devs[unit]; 1281 1282 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 1283 return(ENOMEM); 1284 1285 switch (FUNCTION(dev)) { 1286 case VIDEO_DEV: 1287 return(video_ioctl(bktr, unit, cmd, arg, pr)); 1288 case TUNER_DEV: 1289 return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 1290 } 1291 1292 return(ENXIO); 1293} 1294 1295/* 1296 * 1297 */ 1298paddr_t 1299bktr_mmap(dev_t dev, off_t offset, int nprot) 1300{ 1301 int unit; 1302 bktr_ptr_t bktr; 1303 1304 unit = UNIT(dev); 1305 1306 if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 1307 return(-1); 1308 1309 bktr = bktr_cd.cd_devs[unit]; 1310 1311 if ((vaddr_t)offset < 0) 1312 return(-1); 1313 1314 if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 1315 return(-1); 1316 1317#ifdef __NetBSD__ 1318 return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 1319 (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 1320#else 1321 return(i386_btop(vtophys(bktr->bigbuf) + offset)); 1322#endif 1323} 1324 1325#endif /* __NetBSD__ || __OpenBSD__ */ 1326