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