1 /*- 2 * 1. Redistributions of source code must retain the 3 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Amancio Hasty and 17 * Roger Hardiman 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $FreeBSD: src/sys/dev/bktr/bktr_os.c,v 1.54 2007/02/23 12:18:34 piso Exp $ 34 */ 35 36 /* 37 * This is part of the Driver for Video Capture Cards (Frame grabbers) 38 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 39 * chipset. 40 * Copyright Roger Hardiman and Amancio Hasty. 41 * 42 * bktr_os : This has all the Operating System dependant code, 43 * probe/attach and open/close/ioctl/read/mmap 44 * memory allocation 45 * PCI bus interfacing 46 */ 47 48 #include "opt_bktr.h" /* include any kernel config options */ 49 50 #define FIFO_RISC_DISABLED 0 51 #define ALL_INTS_DISABLED 0 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/conf.h> 56 #include <sys/device.h> 57 #include <sys/uio.h> 58 #include <sys/kernel.h> 59 #include <sys/signalvar.h> 60 #include <sys/malloc.h> 61 #include <sys/mman.h> 62 #include <sys/event.h> 63 #include <sys/bus.h> 64 #include <sys/rman.h> 65 #include <sys/thread2.h> 66 67 #include <vm/vm.h> 68 #include <vm/vm_kern.h> 69 #include <vm/pmap.h> 70 #include <vm/vm_extern.h> 71 72 #include <bus/pci/pcivar.h> 73 #include <bus/pci/pcireg.h> 74 #include <bus/pci/pcidevs.h> 75 76 #include <sys/sysctl.h> 77 int bt848_card = -1; 78 int bt848_tuner = -1; 79 int bt848_reverse_mute = -1; 80 int bt848_format = -1; 81 int bt848_slow_msp_audio = -1; 82 #ifdef BKTR_NEW_MSP34XX_DRIVER 83 int bt848_stereo_once = 0; /* no continuous stereo monitoring */ 84 int bt848_amsound = 0; /* hard-wire AM sound at 6.5 Hz (france), 85 the autoscan seems work well only with FM... */ 86 int bt848_dolby = 0; 87 #endif 88 89 SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 90 SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 91 SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 92 SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 93 SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 94 SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 95 #ifdef BKTR_NEW_MSP34XX_DRIVER 96 SYSCTL_INT(_hw_bt848, OID_AUTO, stereo_once, CTLFLAG_RW, &bt848_stereo_once, 0, ""); 97 SYSCTL_INT(_hw_bt848, OID_AUTO, amsound, CTLFLAG_RW, &bt848_amsound, 0, ""); 98 SYSCTL_INT(_hw_bt848, OID_AUTO, dolby, CTLFLAG_RW, &bt848_dolby, 0, ""); 99 #endif 100 101 #include <dev/video/meteor/ioctl_meteor.h> 102 #include <dev/video/bktr/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 103 #include <dev/video/bktr/bktr_reg.h> 104 #include <dev/video/bktr/bktr_tuner.h> 105 #include <dev/video/bktr/bktr_card.h> 106 #include <dev/video/bktr/bktr_audio.h> 107 #include <dev/video/bktr/bktr_core.h> 108 #include <dev/video/bktr/bktr_os.h> 109 110 #if defined(BKTR_USE_FREEBSD_SMBUS) 111 #include <dev/video/bktr/bktr_i2c.h> 112 113 #include "iicbb_if.h" 114 #include "smbus_if.h" 115 #endif 116 117 static int bktr_probe( device_t dev ); 118 static int bktr_attach( device_t dev ); 119 static int bktr_detach( device_t dev ); 120 static int bktr_shutdown( device_t dev ); 121 static void bktr_intr(void *arg) { common_bktr_intr(arg); } 122 123 static device_method_t bktr_methods[] = { 124 /* Device interface */ 125 DEVMETHOD(device_probe, bktr_probe), 126 DEVMETHOD(device_attach, bktr_attach), 127 DEVMETHOD(device_detach, bktr_detach), 128 DEVMETHOD(device_shutdown, bktr_shutdown), 129 130 #if defined(BKTR_USE_FREEBSD_SMBUS) 131 /* iicbb interface */ 132 DEVMETHOD(iicbb_callback, bti2c_iic_callback), 133 DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), 134 DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), 135 DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), 136 DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), 137 DEVMETHOD(iicbb_reset, bti2c_iic_reset), 138 139 /* smbus interface */ 140 DEVMETHOD(smbus_callback, bti2c_smb_callback), 141 DEVMETHOD(smbus_writeb, bti2c_smb_writeb), 142 DEVMETHOD(smbus_writew, bti2c_smb_writew), 143 DEVMETHOD(smbus_readb, bti2c_smb_readb), 144 #endif 145 146 { 0, 0 } 147 }; 148 149 static driver_t bktr_driver = { 150 "bktr", 151 bktr_methods, 152 sizeof(struct bktr_softc), 153 }; 154 155 static devclass_t bktr_devclass; 156 157 static d_open_t bktr_open; 158 static d_close_t bktr_close; 159 static d_read_t bktr_read; 160 static d_write_t bktr_write; 161 static d_ioctl_t bktr_ioctl; 162 static d_mmap_t bktr_mmap; 163 static d_kqfilter_t bktr_kqfilter; 164 165 static void bktr_filter_detach(struct knote *); 166 static int bktr_filter(struct knote *, long); 167 168 static struct dev_ops bktr_ops = { 169 { "bktr", 0, 0 }, 170 .d_open = bktr_open, 171 .d_close = bktr_close, 172 .d_read = bktr_read, 173 .d_write = bktr_write, 174 .d_ioctl = bktr_ioctl, 175 .d_kqfilter = bktr_kqfilter, 176 .d_mmap = bktr_mmap, 177 }; 178 179 DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, NULL, NULL); 180 MODULE_DEPEND(bktr, bktr_mem, 1,1,1); 181 MODULE_VERSION(bktr, 1); 182 183 /* 184 * the boot time probe routine. 185 */ 186 static int 187 bktr_probe( device_t dev ) 188 { 189 unsigned int type = pci_get_devid(dev); 190 unsigned int rev = pci_get_revid(dev); 191 192 if (PCI_VENDOR(type) == PCI_VENDOR_BROOKTREE) 193 { 194 switch (PCI_PRODUCT(type)) { 195 case PCI_PRODUCT_BROOKTREE_BT848: 196 if (rev == 0x12) 197 device_set_desc(dev, "BrookTree 848A"); 198 else 199 device_set_desc(dev, "BrookTree 848"); 200 return BUS_PROBE_DEFAULT; 201 case PCI_PRODUCT_BROOKTREE_BT849: 202 device_set_desc(dev, "BrookTree 849A"); 203 return BUS_PROBE_DEFAULT; 204 case PCI_PRODUCT_BROOKTREE_BT878: 205 device_set_desc(dev, "BrookTree 878"); 206 return BUS_PROBE_DEFAULT; 207 case PCI_PRODUCT_BROOKTREE_BT879: 208 device_set_desc(dev, "BrookTree 879"); 209 return BUS_PROBE_DEFAULT; 210 } 211 }; 212 213 return ENXIO; 214 } 215 216 217 /* 218 * the attach routine. 219 */ 220 static int 221 bktr_attach( device_t dev ) 222 { 223 u_long latency; 224 u_long fun; 225 u_long val; 226 unsigned int rev; 227 unsigned int unit; 228 int error = 0; 229 #ifdef BROOKTREE_IRQ 230 u_long old_irq, new_irq; 231 #endif 232 233 struct bktr_softc *bktr = device_get_softc(dev); 234 235 unit = device_get_unit(dev); 236 237 /* build the device name for bktr_name() */ 238 ksnprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 239 240 /* 241 * Enable bus mastering and Memory Mapped device 242 */ 243 val = pci_read_config(dev, PCIR_COMMAND, 4); 244 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 245 pci_write_config(dev, PCIR_COMMAND, val, 4); 246 247 /* 248 * Map control/status registers. 249 */ 250 bktr->mem_rid = PCIR_BAR(0); 251 bktr->res_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 252 &bktr->mem_rid, RF_ACTIVE); 253 254 if (!bktr->res_mem) { 255 device_printf(dev, "could not map memory\n"); 256 error = ENXIO; 257 goto fail; 258 } 259 bktr->memt = rman_get_bustag(bktr->res_mem); 260 bktr->memh = rman_get_bushandle(bktr->res_mem); 261 262 263 /* 264 * Disable the brooktree device 265 */ 266 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 267 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 268 269 270 #ifdef BROOKTREE_IRQ /* from the configuration file */ 271 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 272 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 273 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 274 kprintf("bktr%d: attach: irq changed from %d to %d\n", 275 unit, (old_irq & 0xff), (new_irq & 0xff)); 276 #endif 277 278 /* 279 * Allocate our interrupt. 280 */ 281 bktr->irq_rid = 0; 282 bktr->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 283 &bktr->irq_rid, RF_SHAREABLE | RF_ACTIVE); 284 if (bktr->res_irq == NULL) { 285 device_printf(dev, "could not map interrupt\n"); 286 error = ENXIO; 287 goto fail; 288 } 289 290 error = bus_setup_intr(dev, bktr->res_irq, 0, 291 bktr_intr, bktr, &bktr->res_ih, NULL); 292 if (error) { 293 device_printf(dev, "could not setup irq\n"); 294 goto fail; 295 296 } 297 298 299 /* Update the Device Control Register */ 300 /* on Bt878 and Bt879 cards */ 301 fun = pci_read_config( dev, 0x40, 2); 302 fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 303 304 #if defined( BKTR_430_FX_MODE ) 305 if (bootverbose) kprintf("Using 430 FX chipset compatibility mode\n"); 306 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 307 #endif 308 309 #if defined( BKTR_SIS_VIA_MODE ) 310 if (bootverbose) kprintf("Using SiS/VIA chipset compatibility mode\n"); 311 fun = fun | 4; /* Enable SiS/VIA compatibility mode (useful for 312 OPTi chipset motherboards too */ 313 #endif 314 pci_write_config(dev, 0x40, fun, 2); 315 316 #if defined(BKTR_USE_FREEBSD_SMBUS) 317 if (bt848_i2c_attach(dev)) 318 kprintf("bktr%d: i2c_attach: can't attach\n", unit); 319 #endif 320 321 /* 322 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 323 * you have more than four, then 16 would probably be a better value. 324 */ 325 #ifndef BROOKTREE_DEF_LATENCY_VALUE 326 #define BROOKTREE_DEF_LATENCY_VALUE 10 327 #endif 328 latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 329 latency = (latency >> 8) & 0xff; 330 if ( bootverbose ) { 331 if (latency) 332 kprintf("brooktree%d: PCI bus latency is", unit); 333 else 334 kprintf("brooktree%d: PCI bus latency was 0 changing to", 335 unit); 336 } 337 if ( !latency ) { 338 latency = BROOKTREE_DEF_LATENCY_VALUE; 339 pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 340 } 341 if ( bootverbose ) { 342 kprintf(" %d.\n", (int) latency); 343 } 344 345 /* read the pci device id and revision id */ 346 fun = pci_get_devid(dev); 347 rev = pci_get_revid(dev); 348 349 /* call the common attach code */ 350 common_bktr_attach( bktr, unit, fun, rev ); 351 352 /* make the device entries */ 353 make_dev(&bktr_ops, unit, 0, 0, 0444, "bktr%d", unit); 354 make_dev(&bktr_ops, unit+16, 0, 0, 0444, "tuner%d", unit); 355 make_dev(&bktr_ops, unit+32, 0, 0, 0444, "vbi%d" , unit); 356 357 return 0; 358 359 fail: 360 if (bktr->res_irq) 361 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 362 if (bktr->res_mem) 363 bus_release_resource(dev, SYS_RES_IRQ, bktr->mem_rid, bktr->res_mem); 364 return error; 365 366 } 367 368 /* 369 * the detach routine. 370 */ 371 static int 372 bktr_detach( device_t dev ) 373 { 374 struct bktr_softc *bktr = device_get_softc(dev); 375 376 #ifdef BKTR_NEW_MSP34XX_DRIVER 377 /* Disable the soundchip and kernel thread */ 378 if (bktr->msp3400c_info != NULL) 379 msp_detach(bktr); 380 #endif 381 382 /* Disable the brooktree device */ 383 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 384 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 385 386 #if defined(BKTR_USE_FREEBSD_SMBUS) 387 if (bt848_i2c_detach(dev)) 388 kprintf("bktr%d: i2c_attach: can't attach\n", 389 device_get_unit(dev)); 390 #endif 391 #ifdef USE_VBIMUTEX 392 mtx_destroy(&bktr->vbimutex); 393 #endif 394 395 /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ 396 /* The memory is retained by the bktr_mem module so we can unload and */ 397 /* then reload the main bktr driver module */ 398 399 /* removing the ops automatically destroys all related devices */ 400 dev_ops_remove_minor(&bktr_ops, /*0x0f, */device_get_unit(dev)); 401 402 /* 403 * Deallocate resources. 404 */ 405 bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 406 bus_release_resource(dev, SYS_RES_IRQ, bktr->irq_rid, bktr->res_irq); 407 bus_release_resource(dev, SYS_RES_MEMORY, bktr->mem_rid, bktr->res_mem); 408 409 return 0; 410 } 411 412 /* 413 * the shutdown routine. 414 */ 415 static int 416 bktr_shutdown( device_t dev ) 417 { 418 struct bktr_softc *bktr = device_get_softc(dev); 419 420 /* Disable the brooktree device */ 421 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 422 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 423 424 return 0; 425 } 426 427 428 /* 429 * Special Memory Allocation 430 */ 431 vm_offset_t 432 get_bktr_mem( int unit, unsigned size ) 433 { 434 vm_offset_t addr = 0; 435 436 addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 437 0xffffffff, 1<<24, 0); 438 if (addr == 0) 439 addr = (vm_offset_t)contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, 440 0xffffffff, PAGE_SIZE, 0); 441 if (addr == 0) { 442 kprintf("bktr%d: Unable to allocate %d bytes of memory.\n", 443 unit, size); 444 } 445 446 return( addr ); 447 } 448 449 450 /*--------------------------------------------------------- 451 ** 452 ** BrookTree 848 character device driver routines 453 ** 454 **--------------------------------------------------------- 455 */ 456 457 #define VIDEO_DEV 0x00 458 #define TUNER_DEV 0x01 459 #define VBI_DEV 0x02 460 461 #define UNIT(x) ((x) & 0x0f) 462 #define FUNCTION(x) (x >> 4) 463 464 /* 465 * 466 */ 467 static int 468 bktr_open(struct dev_open_args *ap) 469 { 470 cdev_t dev = ap->a_head.a_dev; 471 bktr_ptr_t bktr; 472 int unit; 473 int result; 474 475 unit = UNIT( minor(dev) ); 476 477 /* Get the device data */ 478 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 479 if (bktr == NULL) { 480 /* the device is no longer valid/functioning */ 481 return (ENXIO); 482 } 483 484 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 485 return( ENXIO ); 486 487 /* Record that the device is now busy */ 488 device_busy(devclass_get_device(bktr_devclass, unit)); 489 490 491 if (bt848_card != -1) { 492 if ((bt848_card >> 8 == unit ) && 493 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 494 if ( bktr->bt848_card != (bt848_card & 0xff) ) { 495 bktr->bt848_card = (bt848_card & 0xff); 496 probeCard(bktr, FALSE, unit); 497 } 498 } 499 } 500 501 if (bt848_tuner != -1) { 502 if ((bt848_tuner >> 8 == unit ) && 503 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 504 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 505 bktr->bt848_tuner = (bt848_tuner & 0xff); 506 probeCard(bktr, FALSE, unit); 507 } 508 } 509 } 510 511 if (bt848_reverse_mute != -1) { 512 if ((bt848_reverse_mute >> 8) == unit ) { 513 bktr->reverse_mute = bt848_reverse_mute & 0xff; 514 } 515 } 516 517 if (bt848_slow_msp_audio != -1) { 518 if ((bt848_slow_msp_audio >> 8) == unit ) { 519 bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 520 } 521 } 522 523 #ifdef BKTR_NEW_MSP34XX_DRIVER 524 if (bt848_stereo_once != 0) { 525 if ((bt848_stereo_once >> 8) == unit ) { 526 bktr->stereo_once = (bt848_stereo_once & 0xff); 527 } 528 } 529 530 if (bt848_amsound != -1) { 531 if ((bt848_amsound >> 8) == unit ) { 532 bktr->amsound = (bt848_amsound & 0xff); 533 } 534 } 535 536 if (bt848_dolby != -1) { 537 if ((bt848_dolby >> 8) == unit ) { 538 bktr->dolby = (bt848_dolby & 0xff); 539 } 540 } 541 #endif 542 543 switch ( FUNCTION( minor(dev) ) ) { 544 case VIDEO_DEV: 545 result = video_open( bktr ); 546 break; 547 case TUNER_DEV: 548 result = tuner_open( bktr ); 549 break; 550 case VBI_DEV: 551 result = vbi_open( bktr ); 552 break; 553 default: 554 result = ENXIO; 555 break; 556 } 557 558 /* If there was an error opening the device, undo the busy status */ 559 if (result != 0) 560 device_unbusy(devclass_get_device(bktr_devclass, unit)); 561 return( result ); 562 } 563 564 565 /* 566 * 567 */ 568 static int 569 bktr_close(struct dev_close_args *ap) 570 { 571 cdev_t dev = ap->a_head.a_dev; 572 bktr_ptr_t bktr; 573 int unit; 574 int result; 575 576 unit = UNIT( minor(dev) ); 577 578 /* Get the device data */ 579 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 580 if (bktr == NULL) { 581 /* the device is no longer valid/functioning */ 582 return (ENXIO); 583 } 584 585 switch ( FUNCTION( minor(dev) ) ) { 586 case VIDEO_DEV: 587 result = video_close( bktr ); 588 break; 589 case TUNER_DEV: 590 result = tuner_close( bktr ); 591 break; 592 case VBI_DEV: 593 result = vbi_close( bktr ); 594 break; 595 default: 596 return (ENXIO); 597 break; 598 } 599 600 device_unbusy(devclass_get_device(bktr_devclass, unit)); 601 return( result ); 602 } 603 604 605 /* 606 * 607 */ 608 static int 609 bktr_read(struct dev_read_args *ap) 610 { 611 cdev_t dev = ap->a_head.a_dev; 612 bktr_ptr_t bktr; 613 int unit; 614 615 unit = UNIT(minor(dev)); 616 617 /* Get the device data */ 618 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 619 if (bktr == NULL) { 620 /* the device is no longer valid/functioning */ 621 return (ENXIO); 622 } 623 624 switch ( FUNCTION( minor(dev) ) ) { 625 case VIDEO_DEV: 626 return( video_read( bktr, unit, dev, ap->a_uio ) ); 627 case VBI_DEV: 628 return( vbi_read( bktr, ap->a_uio, ap->a_ioflag ) ); 629 } 630 return( ENXIO ); 631 } 632 633 634 /* 635 * 636 */ 637 static int 638 bktr_write(struct dev_write_args *ap) 639 { 640 return( EINVAL ); /* XXX or ENXIO ? */ 641 } 642 643 644 /* 645 * 646 */ 647 static int 648 bktr_ioctl(struct dev_ioctl_args *ap) 649 { 650 cdev_t dev = ap->a_head.a_dev; 651 u_long cmd = ap->a_cmd; 652 bktr_ptr_t bktr; 653 int unit; 654 655 unit = UNIT(minor(dev)); 656 657 /* Get the device data */ 658 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 659 if (bktr == NULL) { 660 /* the device is no longer valid/functioning */ 661 return (ENXIO); 662 } 663 664 #ifdef BKTR_GPIO_ACCESS 665 if (bktr->bigbuf == 0 && cmd != BT848_GPIO_GET_EN && 666 cmd != BT848_GPIO_SET_EN && cmd != BT848_GPIO_GET_DATA && 667 cmd != BT848_GPIO_SET_DATA) /* no frame buffer allocated (ioctl failed) */ 668 return( ENOMEM ); 669 #else 670 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 671 return( ENOMEM ); 672 #endif 673 674 switch ( FUNCTION( minor(dev) ) ) { 675 case VIDEO_DEV: 676 return( video_ioctl( bktr, unit, cmd, ap->a_data, curthread ) ); 677 case TUNER_DEV: 678 return( tuner_ioctl( bktr, unit, cmd, ap->a_data, curthread ) ); 679 } 680 681 return( ENXIO ); 682 } 683 684 685 /* 686 * 687 */ 688 static int 689 bktr_mmap(struct dev_mmap_args *ap) 690 { 691 cdev_t dev = ap->a_head.a_dev; 692 int unit; 693 bktr_ptr_t bktr; 694 695 unit = UNIT(minor(dev)); 696 697 if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 698 return(EINVAL); 699 700 /* Get the device data */ 701 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 702 if (bktr == NULL) { 703 /* the device is no longer valid/functioning */ 704 return (ENXIO); 705 } 706 707 if (ap->a_nprot & PROT_EXEC) 708 return(EINVAL); 709 710 if (ap->a_offset < 0) 711 return(EINVAL); 712 713 if (ap->a_offset >= bktr->alloc_pages * PAGE_SIZE) 714 return(EINVAL); 715 716 ap->a_result = atop(vtophys(bktr->bigbuf) + ap->a_offset); 717 return(0); 718 } 719 720 static struct filterops bktr_filterops = 721 { FILTEROP_ISFD, NULL, bktr_filter_detach, bktr_filter }; 722 723 static int 724 bktr_kqfilter(struct dev_kqfilter_args *ap) 725 { 726 cdev_t dev = ap->a_head.a_dev; 727 struct knote *kn = ap->a_kn; 728 struct klist *klist; 729 bktr_ptr_t bktr; 730 int unit; 731 732 ap->a_result = 0; 733 734 switch (kn->kn_filter) { 735 case EVFILT_READ: 736 if (FUNCTION(minor(dev)) == VBI_DEV) { 737 unit = UNIT(minor(dev)); 738 /* Get the device data */ 739 bktr = (struct bktr_softc *) 740 devclass_get_softc(bktr_devclass, unit); 741 kn->kn_fop = &bktr_filterops; 742 kn->kn_hook = (caddr_t)bktr; 743 break; 744 } 745 /* fall through */ 746 default: 747 ap->a_result = EOPNOTSUPP; 748 return (0); 749 } 750 751 klist = &bktr->vbi_kq.ki_note; 752 knote_insert(klist, kn); 753 754 return (0); 755 } 756 757 static void 758 bktr_filter_detach(struct knote *kn) 759 { 760 bktr_ptr_t bktr = (bktr_ptr_t)kn->kn_hook; 761 struct klist *klist; 762 763 klist = &bktr->vbi_kq.ki_note; 764 knote_insert(klist, kn); 765 } 766 767 static int 768 bktr_filter(struct knote *kn, long hint) 769 { 770 bktr_ptr_t bktr = (bktr_ptr_t)kn->kn_hook; 771 int ready = 0; 772 773 if (bktr == NULL) { 774 /* the device is no longer valid/functioning */ 775 kn->kn_flags |= (EV_EOF | EV_NODATA); 776 return (1); 777 } 778 779 LOCK_VBI(bktr); 780 crit_enter(); 781 if (bktr->vbisize != 0) 782 ready = 1; 783 crit_exit(); 784 UNLOCK_VBI(bktr); 785 786 return (ready); 787 } 788