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