bktr_os.c revision 52593
1/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 52593 1999-10-28 13:58:17Z roger $ */ 2 3/* 4 * This is part of the Driver for Video Capture Cards (Frame grabbers) 5 * and TV Tuner cards using the Brooktree Bt848, Bt848A, Bt849A, Bt878, Bt879 6 * chipset. 7 * Copyright Roger Hardiman and Amancio Hasty. 8 * 9 * bktr_os : This has all the Operating System dependant code, 10 * probe/attach and open/close/ioctl/read/mmap 11 * memory allocation 12 * PCI bus interfacing 13 * 14 * 15 */ 16 17/* 18 * 1. Redistributions of source code must retain the 19 * Copyright (c) 1997 Amancio Hasty, 1999 Roger Hardiman 20 * All rights reserved. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * This product includes software developed by Amancio Hasty and 33 * Roger Hardiman 34 * 4. The name of the author may not be used to endorse or promote products 35 * derived from this software without specific prior written permission. 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 38 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 41 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 43 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 46 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 47 * POSSIBILITY OF SUCH DAMAGE. 48 */ 49 50 51#ifdef __FreeBSD__ 52#include "bktr.h" 53#include "opt_bktr.h" 54#include "opt_devfs.h" 55#endif /* __FreeBSD__ */ 56 57#if defined(__NetBSD__) || defined(__OpenBSD__) 58#include "bktr.h" 59#include "pci.h" 60#endif /* __NetBSD__ || __OpenBSD__ */ 61 62#define FIFO_RISC_DISABLED 0 63#define ALL_INTS_DISABLED 0 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/conf.h> 68#include <sys/uio.h> 69#include <sys/kernel.h> 70#include <sys/signalvar.h> 71#include <sys/mman.h> 72#include <sys/poll.h> 73#include <sys/select.h> 74#include <sys/vnode.h> 75 76#include <vm/vm.h> 77#include <vm/vm_kern.h> 78#include <vm/pmap.h> 79#include <vm/vm_extern.h> 80 81/*******************/ 82/* *** FreeBSD *** */ 83/*******************/ 84#ifdef __FreeBSD__ 85 86#if (__FreeBSD_version < 400000) 87#ifdef DEVFS 88#include <sys/devfsext.h> 89#endif /* DEVFS */ 90#endif 91 92#if (__FreeBSD_version >=400000) || (NSMBUS > 0) 93#include <sys/bus.h> /* used by smbus and newbus */ 94#endif 95 96#if (__FreeBSD_version >=400000) 97#include <machine/bus.h> /* used by newbus */ 98#include <sys/rman.h> /* used by newbus */ 99#include <machine/resource.h> /* used by newbus */ 100#endif 101 102#include <machine/clock.h> /* for DELAY */ 103#include <pci/pcivar.h> 104#include <pci/pcireg.h> 105 106#include <machine/ioctl_meteor.h> 107#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 108#include <dev/bktr/bktr_reg.h> 109#include <dev/bktr/bktr_tuner.h> 110#include <dev/bktr/bktr_card.h> 111#include <dev/bktr/bktr_audio.h> 112#include <dev/bktr/bktr_core.h> 113#include <dev/bktr/bktr_os.h> 114 115#if (NSMBUS > 0) 116#include <dev/bktr/bktr_i2c.h> 117#endif 118 119#include <sys/sysctl.h> 120int bt848_card = -1; 121int bt848_tuner = -1; 122int bt848_reverse_mute = -1; 123int bt848_format = -1; 124 125SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 126SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 127SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 128SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 129SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 130 131#if (__FreeBSD_version >= 300000) 132 typedef u_long ioctl_cmd_t; 133#endif 134 135#if (__FreeBSD__ == 2) 136typedef int ioctl_cmd_t; 137#define PCIR_REVID PCI_CLASS_REG 138#endif 139#endif /* __FreeBSD__ */ 140 141 142/****************/ 143/* *** BSDI *** */ 144/****************/ 145#ifdef __bsdi__ 146#endif /* __bsdi__ */ 147 148 149/**************************/ 150/* *** OpenBSD/NetBSD *** */ 151/**************************/ 152#if defined(__NetBSD__) || defined(__OpenBSD__) 153#endif /* __NetBSD__ || __OpenBSD__ */ 154 155 156 157/****************************/ 158/* *** FreeBSD 4.x code *** */ 159/****************************/ 160#if (__FreeBSD_version >= 400000) 161 162static int bktr_probe( device_t dev ); 163static int bktr_attach( device_t dev ); 164static int bktr_detach( device_t dev ); 165static int bktr_shutdown( device_t dev ); 166static void bktr_intr(void *arg) { common_bktr_intr(arg); } 167 168static device_method_t bktr_methods[] = { 169 /* Device interface */ 170 DEVMETHOD(device_probe, bktr_probe), 171 DEVMETHOD(device_attach, bktr_attach), 172 DEVMETHOD(device_detach, bktr_detach), 173 DEVMETHOD(device_shutdown, bktr_shutdown), 174 175 { 0, 0 } 176}; 177 178static driver_t bktr_driver = { 179 "bktr", 180 bktr_methods, 181 sizeof(struct bktr_softc), 182}; 183 184static devclass_t bktr_devclass; 185 186static d_open_t bktr_open; 187static d_close_t bktr_close; 188static d_read_t bktr_read; 189static d_write_t bktr_write; 190static d_ioctl_t bktr_ioctl; 191static d_mmap_t bktr_mmap; 192static d_poll_t bktr_poll; 193 194#define CDEV_MAJOR 92 195static struct cdevsw bktr_cdevsw = { 196 /* open */ bktr_open, 197 /* close */ bktr_close, 198 /* read */ bktr_read, 199 /* write */ bktr_write, 200 /* ioctl */ bktr_ioctl, 201 /* poll */ bktr_poll, 202 /* mmap */ bktr_mmap, 203 /* strategy */ nostrategy, 204 /* name */ "bktr", 205 /* maj */ CDEV_MAJOR, 206 /* dump */ nodump, 207 /* psize */ nopsize, 208 /* flags */ 0, 209 /* bmaj */ -1 210}; 211 212DEV_DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, bktr_cdevsw, 0, 0); 213 214 215/* 216 * the boot time probe routine. 217 */ 218static int 219bktr_probe( device_t dev ) 220{ 221 unsigned int type = pci_get_devid(dev); 222 unsigned int rev = pci_get_revid(dev); 223 224 switch (type) { 225 case BROOKTREE_848_PCI_ID: 226 if (rev == 0x12) device_set_desc(dev, "BrookTree 848A"); 227 else device_set_desc(dev, "BrookTree 848"); 228 return 0; 229 case BROOKTREE_849_PCI_ID: 230 device_set_desc(dev, "BrookTree 849A"); 231 return 0; 232 case BROOKTREE_878_PCI_ID: 233 device_set_desc(dev, "BrookTree 878"); 234 return 0; 235 case BROOKTREE_879_PCI_ID: 236 device_set_desc(dev, "BrookTree 879"); 237 return 0; 238 }; 239 240 return ENXIO; 241} 242 243 244/* 245 * the attach routine. 246 */ 247static int 248bktr_attach( device_t dev ) 249{ 250 bt848_ptr_t bt848; 251 u_long latency; 252 u_long fun; 253 u_long val; 254 unsigned int rev; 255 unsigned int unit; 256 int error = 0; 257 int rid; 258#ifdef BROOKTREE_IRQ 259 u_long old_irq, new_irq; 260#endif 261 262 struct bktr_softc *bktr = device_get_softc(dev); 263 264 unit = device_get_unit(dev); 265 266 /* 267 * Enable bus mastering and Memory Mapped device 268 */ 269 val = pci_read_config(dev, PCIR_COMMAND, 4); 270 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 271 pci_write_config(dev, PCIR_COMMAND, val, 4); 272 273 /* 274 * Map control/status registers. 275 */ 276 rid = PCI_MAP_REG_START; 277 bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 278 0, ~0, 1, RF_ACTIVE); 279 280 if (!bktr->res_mem) { 281 device_printf(dev, "could not map memory\n"); 282 error = ENXIO; 283 goto fail; 284 } 285 bktr->base = rman_get_virtual(bktr->res_mem); /* XXX use bus_space */ 286 287 /* 288 * Disable the brooktree device 289 */ 290 bt848 = bktr->base; 291 bt848->int_mask = ALL_INTS_DISABLED; 292 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; 293 294 295#ifdef BROOKTREE_IRQ /* from the configuration file */ 296 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 297 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 298 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 299 printf("bktr%d: attach: irq changed from %d to %d\n", 300 unit, (old_irq & 0xff), (new_irq & 0xff)); 301#endif 302 303 /* 304 * Allocate our interrupt. 305 */ 306 rid = 0; 307 bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 308 RF_SHAREABLE | RF_ACTIVE); 309 if (bktr->res_irq == NULL) { 310 device_printf(dev, "could not map interrupt\n"); 311 error = ENXIO; 312 goto fail; 313 } 314 315 error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_NET, 316 bktr_intr, bktr, &bktr->res_ih); 317 if (error) { 318 device_printf(dev, "could not setup irq\n"); 319 goto fail; 320 321 } 322 323 324 /* Update the Device Control Register */ 325 /* on Bt878 and Bt879 cards */ 326 fun = pci_read_config( dev, 0x40, 2); 327 fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 328 329#if defined( BKTR_430_FX_MODE ) 330 if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 331 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 332#endif 333 334#if defined( BKTR_SIS_VIA_MODE ) 335 if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 336 fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 337 OPTi chipset motherboards too */ 338#endif 339 pci_write_config(dev, 0x40, fun, 2); 340 341 342 /* XXX call bt848_i2c dependent attach() routine */ 343#if (NSMBUS > 0) 344 if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc)) 345 printf("bktr%d: i2c_attach: can't attach\n", unit); 346#endif 347 348 349/* 350 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 351 * you have more than four, then 16 would probably be a better value. 352 */ 353#ifndef BROOKTREE_DEF_LATENCY_VALUE 354#define BROOKTREE_DEF_LATENCY_VALUE 10 355#endif 356 latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 357 latency = (latency >> 8) & 0xff; 358 if ( bootverbose ) { 359 if (latency) 360 printf("brooktree%d: PCI bus latency is", unit); 361 else 362 printf("brooktree%d: PCI bus latency was 0 changing to", 363 unit); 364 } 365 if ( !latency ) { 366 latency = BROOKTREE_DEF_LATENCY_VALUE; 367 pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 368 } 369 if ( bootverbose ) { 370 printf(" %d.\n", (int) latency); 371 } 372 373 /* read the pci device id and revision id */ 374 fun = pci_get_devid(dev); 375 rev = pci_get_revid(dev); 376 377 /* call the common attach code */ 378 common_bktr_attach( bktr, unit, fun, rev ); 379 380 make_dev(&bktr_cdevsw, unit, 0, 0, 0444, "bktr%d", unit); 381 make_dev(&bktr_cdevsw, unit+16, 0, 0, 0444, "tuner%d", unit); 382 make_dev(&bktr_cdevsw, unit+32, 0, 0, 0444, "vbi%d", unit); 383 384 return 0; 385 386fail: 387 return error; 388 389} 390 391/* 392 * the detach routine. 393 */ 394static int 395bktr_detach( device_t dev ) 396{ 397 struct bktr_softc *bktr = device_get_softc(dev); 398 bt848_ptr_t bt848; 399 400 /* Disable the brooktree device */ 401 bt848 = bktr->base; 402 bt848->int_mask = ALL_INTS_DISABLED; 403 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; 404 405 /* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */ 406 407 /* 408 * Deallocate resources. 409 */ 410 bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 411 bus_release_resource(dev, SYS_RES_IRQ, 0, bktr->res_irq); 412 bus_release_resource(dev, SYS_RES_MEMORY, PCI_MAP_REG_START, bktr->res_mem); 413 414 return 0; 415} 416 417/* 418 * the shutdown routine. 419 */ 420static int 421bktr_shutdown( device_t dev ) 422{ 423 struct bktr_softc *bktr = device_get_softc(dev); 424 bt848_ptr_t bt848; 425 426 /* Disable the brooktree device */ 427 bt848 = bktr->base; 428 bt848->int_mask = ALL_INTS_DISABLED; 429 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; 430 431 return 0; 432} 433 434 435/* 436 * Special Memory Allocation 437 */ 438vm_offset_t 439get_bktr_mem( int unit, unsigned size ) 440{ 441 vm_offset_t addr = 0; 442 443 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 444 if (addr == 0) 445 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 446 if (addr == 0) { 447 printf("bktr%d: Unable to allocate %d bytes of memory.\n", 448 unit, size); 449 } 450 451 return( addr ); 452} 453 454 455/*--------------------------------------------------------- 456** 457** BrookTree 848 character device driver routines 458** 459**--------------------------------------------------------- 460*/ 461 462#define VIDEO_DEV 0x00 463#define TUNER_DEV 0x01 464#define VBI_DEV 0x02 465 466#define UNIT(x) ((x) & 0x0f) 467#define FUNCTION(x) (x >> 4) 468 469/* 470 * 471 */ 472int 473bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) 474{ 475 bktr_ptr_t bktr; 476 int unit; 477 int result; 478 479 unit = UNIT( minor(dev) ); 480 481 /* Get the device data */ 482 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 483 if (bktr == NULL) { 484 /* the device is no longer valid/functioning */ 485 return (ENXIO); 486 } 487 488 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 489 return( ENXIO ); 490 491 /* Record that the device is now busy */ 492 device_busy(devclass_get_device(bktr_devclass, unit)); 493 494 495 if (bt848_card != -1) { 496 if ((bt848_card >> 8 == unit ) && 497 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 498 if ( bktr->bt848_card != (bt848_card & 0xff) ) { 499 bktr->bt848_card = (bt848_card & 0xff); 500 probeCard(bktr, FALSE, unit); 501 } 502 } 503 } 504 505 if (bt848_tuner != -1) { 506 if ((bt848_tuner >> 8 == unit ) && 507 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 508 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 509 bktr->bt848_tuner = (bt848_tuner & 0xff); 510 probeCard(bktr, FALSE, unit); 511 } 512 } 513 } 514 515 if (bt848_reverse_mute != -1) { 516 if (((bt848_reverse_mute >> 8) == unit ) && 517 ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) { 518 bktr->reverse_mute = bt848_reverse_mute & 0xff; 519 bt848_reverse_mute = -1; 520 } 521 } 522 523 switch ( FUNCTION( minor(dev) ) ) { 524 case VIDEO_DEV: 525 result = video_open( bktr ); 526 break; 527 case TUNER_DEV: 528 result = tuner_open( bktr ); 529 break; 530 case VBI_DEV: 531 result = vbi_open( bktr ); 532 break; 533 default: 534 result = ENXIO; 535 break; 536 } 537 538 /* If there was an error opening the device, undo the busy status */ 539 if (result != 0) 540 device_unbusy(devclass_get_device(bktr_devclass, unit)); 541 return( result ); 542} 543 544 545/* 546 * 547 */ 548int 549bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) 550{ 551 bktr_ptr_t bktr; 552 int unit; 553 int result; 554 555 unit = UNIT( minor(dev) ); 556 557 /* Get the device data */ 558 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 559 if (bktr == NULL) { 560 /* the device is no longer valid/functioning */ 561 return (ENXIO); 562 } 563 564 switch ( FUNCTION( minor(dev) ) ) { 565 case VIDEO_DEV: 566 result = video_close( bktr ); 567 break; 568 case TUNER_DEV: 569 result = tuner_close( bktr ); 570 break; 571 case VBI_DEV: 572 result = vbi_close( bktr ); 573 break; 574 default: 575 return (ENXIO); 576 break; 577 } 578 579 device_unbusy(devclass_get_device(bktr_devclass, unit)); 580 return( result ); 581} 582 583 584/* 585 * 586 */ 587int 588bktr_read( dev_t dev, struct uio *uio, int ioflag ) 589{ 590 bktr_ptr_t bktr; 591 int unit; 592 593 unit = UNIT(minor(dev)); 594 595 /* Get the device data */ 596 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 597 if (bktr == NULL) { 598 /* the device is no longer valid/functioning */ 599 return (ENXIO); 600 } 601 602 switch ( FUNCTION( minor(dev) ) ) { 603 case VIDEO_DEV: 604 return( video_read( bktr, unit, dev, uio ) ); 605 case VBI_DEV: 606 return( vbi_read( bktr, uio, ioflag ) ); 607 } 608 return( ENXIO ); 609} 610 611 612/* 613 * 614 */ 615int 616bktr_write( dev_t dev, struct uio *uio, int ioflag ) 617{ 618 return( EINVAL ); /* XXX or ENXIO ? */ 619} 620 621 622/* 623 * 624 */ 625int 626bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) 627{ 628 bktr_ptr_t bktr; 629 int unit; 630 631 unit = UNIT(minor(dev)); 632 633 /* Get the device data */ 634 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 635 if (bktr == NULL) { 636 /* the device is no longer valid/functioning */ 637 return (ENXIO); 638 } 639 640 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 641 return( ENOMEM ); 642 643 switch ( FUNCTION( minor(dev) ) ) { 644 case VIDEO_DEV: 645 return( video_ioctl( bktr, unit, cmd, arg, pr ) ); 646 case TUNER_DEV: 647 return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); 648 } 649 650 return( ENXIO ); 651} 652 653 654/* 655 * 656 */ 657int 658bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 659{ 660 int unit; 661 bktr_ptr_t bktr; 662 663 unit = UNIT(minor(dev)); 664 665 if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 666 return( -1 ); 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 (nprot & PROT_EXEC) 676 return( -1 ); 677 678 if (offset < 0) 679 return( -1 ); 680 681 if (offset >= bktr->alloc_pages * PAGE_SIZE) 682 return( -1 ); 683 684 return( i386_btop(vtophys(bktr->bigbuf) + offset) ); 685} 686 687int bktr_poll( dev_t dev, int events, struct proc *p) 688{ 689 int unit; 690 bktr_ptr_t bktr; 691 int revents = 0; 692 693 unit = UNIT(minor(dev)); 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 disable_intr(); 703 704 if (events & (POLLIN | POLLRDNORM)) { 705 706 switch ( FUNCTION( minor(dev) ) ) { 707 case VBI_DEV: 708 if(bktr->vbisize == 0) 709 selrecord(p, &bktr->vbi_select); 710 else 711 revents |= events & (POLLIN | POLLRDNORM); 712 break; 713 } 714 } 715 716 enable_intr(); 717 718 return (revents); 719} 720 721#endif /* FreeBSD 4.x specific kernel interface routines */ 722 723/**********************************/ 724/* *** FreeBSD 2.2.x and 3.x *** */ 725/**********************************/ 726 727#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3)) 728 729static bktr_reg_t brooktree[ NBKTR ]; 730 731static const char* bktr_probe( pcici_t tag, pcidi_t type ); 732static void bktr_attach( pcici_t tag, int unit ); 733static void bktr_intr(void *arg) { common_bktr_intr(arg); } 734 735static u_long bktr_count; 736 737static struct pci_device bktr_device = { 738 "bktr", 739 bktr_probe, 740 bktr_attach, 741 &bktr_count 742}; 743 744DATA_SET (pcidevice_set, bktr_device); 745 746static d_open_t bktr_open; 747static d_close_t bktr_close; 748static d_read_t bktr_read; 749static d_write_t bktr_write; 750static d_ioctl_t bktr_ioctl; 751static d_mmap_t bktr_mmap; 752static d_poll_t bktr_poll; 753 754#define CDEV_MAJOR 92 755static struct cdevsw bktr_cdevsw = 756{ 757 bktr_open, bktr_close, bktr_read, bktr_write, 758 bktr_ioctl, nostop, nullreset, nodevtotty, 759 bktr_poll, bktr_mmap, NULL, "bktr", 760 NULL, -1 761}; 762 763static int bktr_devsw_installed; 764 765static void 766bktr_drvinit( void *unused ) 767{ 768 dev_t dev; 769 770 if ( ! bktr_devsw_installed ) { 771 dev = makedev(CDEV_MAJOR, 0); 772 cdevsw_add(&dev,&bktr_cdevsw, NULL); 773 bktr_devsw_installed = 1; 774 } 775} 776 777SYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL) 778 779/* 780 * the boot time probe routine. 781 */ 782static const char* 783bktr_probe( pcici_t tag, pcidi_t type ) 784{ 785 unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff; 786 787 switch (type) { 788 case BROOKTREE_848_PCI_ID: 789 if (rev == 0x12) return("BrookTree 848A"); 790 else return("BrookTree 848"); 791 case BROOKTREE_849_PCI_ID: 792 return("BrookTree 849A"); 793 case BROOKTREE_878_PCI_ID: 794 return("BrookTree 878"); 795 case BROOKTREE_879_PCI_ID: 796 return("BrookTree 879"); 797 }; 798 799 return ((char *)0); 800} 801 802/* 803 * the attach routine. 804 */ 805static void 806bktr_attach( pcici_t tag, int unit ) 807{ 808 bktr_ptr_t bktr; 809 bt848_ptr_t bt848; 810 u_long latency; 811 u_long fun; 812 unsigned int rev; 813#ifdef BROOKTREE_IRQ 814 u_long old_irq, new_irq; 815#endif 816 817 bktr = &brooktree[unit]; 818 819 if (unit >= NBKTR) { 820 printf("brooktree%d: attach: only %d units configured.\n", 821 unit, NBKTR); 822 printf("brooktree%d: attach: invalid unit number.\n", unit); 823 return; 824 } 825 826 /* Enable Memory Mapping */ 827 fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 828 pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2); 829 830 /* Enable Bus Mastering */ 831 fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 832 pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4); 833 834 bktr->tag = tag; 835 836 837 /* 838 * Map control/status registers 839 */ 840 pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &bktr->base, 841 &bktr->phys_base ); 842 843 /* 844 * Disable the brooktree device 845 */ 846 bt848 = bktr->base; 847 bt848->int_mask = ALL_INTS_DISABLED; 848 bt848->gpio_dma_ctl = FIFO_RISC_DISABLED; 849 850#ifdef BROOKTREE_IRQ /* from the configuration file */ 851 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 852 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 853 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 854 printf("bktr%d: attach: irq changed from %d to %d\n", 855 unit, (old_irq & 0xff), (new_irq & 0xff)); 856#endif 857 858 /* 859 * setup the interrupt handling routine 860 */ 861 pci_map_int(tag, bktr_intr, (void*) bktr, &net_imask); 862 863 864 /* Update the Device Control Register */ 865 /* on Bt878 and Bt879 cards */ 866 fun = pci_conf_read(tag, 0x40); 867 fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 868 869#if defined( BKTR_430_FX_MODE ) 870 if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 871 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 872#endif 873 874#if defined( BKTR_SIS_VIA_MODE ) 875 if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 876 fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 877 OPTi chipset motherboards too */ 878#endif 879 pci_conf_write(tag, 0x40, fun); 880 881 882 /* XXX call bt848_i2c dependent attach() routine */ 883#if (NSMBUS > 0) 884 if (bt848_i2c_attach(unit, bktr->base, &bktr->i2c_sc)) 885 printf("bktr%d: i2c_attach: can't attach\n", unit); 886#endif 887 888 889/* 890 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 891 * you have more than four, then 16 would probably be a better value. 892 */ 893#ifndef BROOKTREE_DEF_LATENCY_VALUE 894#define BROOKTREE_DEF_LATENCY_VALUE 10 895#endif 896 latency = pci_conf_read(tag, PCI_LATENCY_TIMER); 897 latency = (latency >> 8) & 0xff; 898 if ( bootverbose ) { 899 if (latency) 900 printf("brooktree%d: PCI bus latency is", unit); 901 else 902 printf("brooktree%d: PCI bus latency was 0 changing to", 903 unit); 904 } 905 if ( !latency ) { 906 latency = BROOKTREE_DEF_LATENCY_VALUE; 907 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); 908 } 909 if ( bootverbose ) { 910 printf(" %d.\n", (int) latency); 911 } 912 913 914 /* read the pci device id and revision id */ 915 fun = pci_conf_read(tag, PCI_ID_REG); 916 rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff; 917 918 /* call the common attach code */ 919 common_bktr_attach( bktr, unit, fun, rev ); 920 921#ifdef DEVFS 922 /* XXX This just throw away the token, which should probably be fixed when 923 DEVFS is finally made really operational. */ 924 devfs_add_devswf(&bktr_cdevsw, unit, DV_CHR, 0, 0, 0444, "bktr%d", unit); 925 devfs_add_devswf(&bktr_cdevsw, unit+16, DV_CHR, 0, 0, 0444, "tuner%d", unit); 926 devfs_add_devswf(&bktr_cdevsw, unit+32, DV_CHR, 0, 0, 0444, "vbi%d", unit); 927#endif /* DEVFS */ 928 929} 930 931 932/* 933 * Special Memory Allocation 934 */ 935vm_offset_t 936get_bktr_mem( int unit, unsigned size ) 937{ 938 vm_offset_t addr = 0; 939 940 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24); 941 if (addr == 0) 942 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 943 PAGE_SIZE); 944 if (addr == 0) { 945 printf("bktr%d: Unable to allocate %d bytes of memory.\n", 946 unit, size); 947 } 948 949 return( addr ); 950} 951 952/*--------------------------------------------------------- 953** 954** BrookTree 848 character device driver routines 955** 956**--------------------------------------------------------- 957*/ 958 959 960#define VIDEO_DEV 0x00 961#define TUNER_DEV 0x01 962#define VBI_DEV 0x02 963 964#define UNIT(x) ((x) & 0x0f) 965#define FUNCTION(x) ((x >> 4) & 0x0f) 966 967 968/* 969 * 970 */ 971int 972bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) 973{ 974 bktr_ptr_t bktr; 975 int unit; 976 977 unit = UNIT( minor(dev) ); 978 if (unit >= NBKTR) /* unit out of range */ 979 return( ENXIO ); 980 981 bktr = &(brooktree[ unit ]); 982 983 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 984 return( ENXIO ); 985 986 987 if (bt848_card != -1) { 988 if ((bt848_card >> 8 == unit ) && 989 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 990 if ( bktr->bt848_card != (bt848_card & 0xff) ) { 991 bktr->bt848_card = (bt848_card & 0xff); 992 probeCard(bktr, FALSE, unit); 993 } 994 } 995 } 996 997 if (bt848_tuner != -1) { 998 if ((bt848_tuner >> 8 == unit ) && 999 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 1000 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 1001 bktr->bt848_tuner = (bt848_tuner & 0xff); 1002 probeCard(bktr, FALSE, unit); 1003 } 1004 } 1005 } 1006 1007 if (bt848_reverse_mute != -1) { 1008 if (((bt848_reverse_mute >> 8) == unit ) && 1009 ((bt848_reverse_mute & 0xff) < Bt848_MAX_TUNER) ) { 1010 bktr->reverse_mute = bt848_reverse_mute & 0xff; 1011 bt848_reverse_mute = -1; 1012 } 1013 } 1014 1015 1016 switch ( FUNCTION( minor(dev) ) ) { 1017 case VIDEO_DEV: 1018 return( video_open( bktr ) ); 1019 case TUNER_DEV: 1020 return( tuner_open( bktr ) ); 1021 case VBI_DEV: 1022 return( vbi_open( bktr ) ); 1023 } 1024 return( ENXIO ); 1025} 1026 1027 1028/* 1029 * 1030 */ 1031int 1032bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) 1033{ 1034 bktr_ptr_t bktr; 1035 int unit; 1036 1037 unit = UNIT( minor(dev) ); 1038 if (unit >= NBKTR) /* unit out of range */ 1039 return( ENXIO ); 1040 1041 bktr = &(brooktree[ unit ]); 1042 1043 switch ( FUNCTION( minor(dev) ) ) { 1044 case VIDEO_DEV: 1045 return( video_close( bktr ) ); 1046 case TUNER_DEV: 1047 return( tuner_close( bktr ) ); 1048 case VBI_DEV: 1049 return( vbi_close( bktr ) ); 1050 } 1051 1052 return( ENXIO ); 1053} 1054 1055/* 1056 * 1057 */ 1058int 1059bktr_read( dev_t dev, struct uio *uio, int ioflag ) 1060{ 1061 bktr_ptr_t bktr; 1062 int unit; 1063 1064 unit = UNIT(minor(dev)); 1065 if (unit >= NBKTR) /* unit out of range */ 1066 return( ENXIO ); 1067 1068 bktr = &(brooktree[unit]); 1069 1070 switch ( FUNCTION( minor(dev) ) ) { 1071 case VIDEO_DEV: 1072 return( video_read( bktr, unit, dev, uio ) ); 1073 case VBI_DEV: 1074 return( vbi_read( bktr, uio, ioflag ) ); 1075 } 1076 return( ENXIO ); 1077} 1078 1079 1080/* 1081 * 1082 */ 1083int 1084bktr_write( dev_t dev, struct uio *uio, int ioflag ) 1085{ 1086 return( EINVAL ); /* XXX or ENXIO ? */ 1087} 1088 1089/* 1090 * 1091 */ 1092int 1093bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) 1094{ 1095 bktr_ptr_t bktr; 1096 int unit; 1097 1098 unit = UNIT(minor(dev)); 1099 if (unit >= NBKTR) /* unit out of range */ 1100 return( ENXIO ); 1101 1102 bktr = &(brooktree[ unit ]); 1103 1104 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 1105 return( ENOMEM ); 1106 1107 switch ( FUNCTION( minor(dev) ) ) { 1108 case VIDEO_DEV: 1109 return( video_ioctl( bktr, unit, cmd, arg, pr ) ); 1110 case TUNER_DEV: 1111 return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); 1112 } 1113 1114 return( ENXIO ); 1115} 1116 1117/* 1118 * bktr_mmap. 1119 * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually 1120 * edit the line below and change "vm_offset_t" to "int" 1121 */ 1122int bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 1123 1124{ 1125 int unit; 1126 bktr_ptr_t bktr; 1127 1128 unit = UNIT(minor(dev)); 1129 1130 if (unit >= NBKTR || FUNCTION(minor(dev)) > 0) 1131 return( -1 ); 1132 1133 bktr = &(brooktree[ unit ]); 1134 1135 if (nprot & PROT_EXEC) 1136 return( -1 ); 1137 1138 if (offset < 0) 1139 return( -1 ); 1140 1141 if (offset >= bktr->alloc_pages * PAGE_SIZE) 1142 return( -1 ); 1143 1144 return( i386_btop(vtophys(bktr->bigbuf) + offset) ); 1145} 1146 1147int bktr_poll( dev_t dev, int events, struct proc *p) 1148{ 1149 int unit; 1150 bktr_ptr_t bktr; 1151 int revents = 0; 1152 1153 unit = UNIT(minor(dev)); 1154 1155 if (unit >= NBKTR) 1156 return( -1 ); 1157 1158 bktr = &(brooktree[ unit ]); 1159 1160 disable_intr(); 1161 1162 if (events & (POLLIN | POLLRDNORM)) { 1163 1164 switch ( FUNCTION( minor(dev) ) ) { 1165 case VBI_DEV: 1166 if(bktr->vbisize == 0) 1167 selrecord(p, &bktr->vbi_select); 1168 else 1169 revents |= events & (POLLIN | POLLRDNORM); 1170 break; 1171 } 1172 } 1173 1174 enable_intr(); 1175 1176 return (revents); 1177} 1178 1179 1180#endif /* FreeBSD 2.2.x and 3.x specific kernel interface routines */ 1181 1182 1183/*****************/ 1184/* *** BSDI *** */ 1185/*****************/ 1186 1187#if defined(__bsdi__) 1188#endif /* __bsdi__ BSDI specific kernel interface routines */ 1189 1190 1191/*****************************/ 1192/* *** OpenBSD / NetBSD *** */ 1193/*****************************/ 1194#if defined(__NetBSD__) || defined(__OpenBSD__) 1195#endif /* __NetBSD__ || __OpenBSD__ */ 1196 1197