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