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