bktr_os.c revision 62112
1/* $FreeBSD: head/sys/dev/bktr/bktr_os.c 62112 2000-06-26 09:41:32Z 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_devfs.h" 54#endif /* __FreeBSD__ */ 55 56#include "opt_bktr.h" /* include any kernel config options */ 57 58#define FIFO_RISC_DISABLED 0 59#define ALL_INTS_DISABLED 0 60 61#include <sys/param.h> 62#include <sys/systm.h> 63#include <sys/conf.h> 64#include <sys/uio.h> 65#include <sys/kernel.h> 66#include <sys/signalvar.h> 67#include <sys/mman.h> 68#include <sys/poll.h> 69#include <sys/select.h> 70#include <sys/vnode.h> 71 72#include <vm/vm.h> 73#include <vm/vm_kern.h> 74#include <vm/pmap.h> 75#include <vm/vm_extern.h> 76 77/*******************/ 78/* *** FreeBSD *** */ 79/*******************/ 80#ifdef __FreeBSD__ 81 82#if (__FreeBSD_version < 400000) 83#ifdef DEVFS 84#include <sys/devfsext.h> 85#endif /* DEVFS */ 86#endif 87 88#if (__FreeBSD_version >=400000) || (NSMBUS > 0) 89#include <sys/bus.h> /* used by smbus and newbus */ 90#endif 91 92#if (__FreeBSD_version >=300000) 93#include <machine/bus_memio.h> /* used by bus space */ 94#include <machine/bus.h> /* used by bus space and newbus */ 95#include <sys/bus.h> 96#endif 97 98#if (__FreeBSD_version >=400000) 99#include <sys/rman.h> /* used by newbus */ 100#include <machine/resource.h> /* used by newbus */ 101#endif 102 103 104#include <machine/clock.h> /* for DELAY */ 105#include <pci/pcivar.h> 106#include <pci/pcireg.h> 107#endif 108 109#ifdef __NetBSD__ 110#include <dev/ic/bt8xx.h> /* NetBSD location for .h files */ 111#include <dev/pci/bktr/bktr_reg.h> 112#include <dev/pci/bktr/bktr_tuner.h> 113#include <dev/pci/bktr/bktr_card.h> 114#include <dev/pci/bktr/bktr_audio.h> 115#include <dev/pci/bktr/bktr_core.h> 116#include <dev/pci/bktr/bktr_os.h> 117#else /* Traditional location for .h files */ 118#include <machine/ioctl_meteor.h> 119#include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ 120#include <dev/bktr/bktr_reg.h> 121#include <dev/bktr/bktr_tuner.h> 122#include <dev/bktr/bktr_card.h> 123#include <dev/bktr/bktr_audio.h> 124#include <dev/bktr/bktr_core.h> 125#include <dev/bktr/bktr_os.h> 126#endif 127 128#if defined(__FreeBSD__) 129#if (NSMBUS > 0) 130#include <dev/bktr/bktr_i2c.h> 131#endif 132 133#include <sys/sysctl.h> 134int bt848_card = -1; 135int bt848_tuner = -1; 136int bt848_reverse_mute = -1; 137int bt848_format = -1; 138int bt848_slow_msp_audio = -1; 139 140SYSCTL_NODE(_hw, OID_AUTO, bt848, CTLFLAG_RW, 0, "Bt848 Driver mgmt"); 141SYSCTL_INT(_hw_bt848, OID_AUTO, card, CTLFLAG_RW, &bt848_card, -1, ""); 142SYSCTL_INT(_hw_bt848, OID_AUTO, tuner, CTLFLAG_RW, &bt848_tuner, -1, ""); 143SYSCTL_INT(_hw_bt848, OID_AUTO, reverse_mute, CTLFLAG_RW, &bt848_reverse_mute, -1, ""); 144SYSCTL_INT(_hw_bt848, OID_AUTO, format, CTLFLAG_RW, &bt848_format, -1, ""); 145SYSCTL_INT(_hw_bt848, OID_AUTO, slow_msp_audio, CTLFLAG_RW, &bt848_slow_msp_audio, -1, ""); 146#endif 147 148#if (__FreeBSD__ == 2) 149#define PCIR_REVID PCI_CLASS_REG 150#endif 151 152 153/****************/ 154/* *** BSDI *** */ 155/****************/ 156#ifdef __bsdi__ 157#endif /* __bsdi__ */ 158 159 160/**************************/ 161/* *** OpenBSD/NetBSD *** */ 162/**************************/ 163#if defined(__NetBSD__) || defined(__OpenBSD__) 164#include <sys/device.h> 165#include <dev/pci/pcivar.h> 166#include <dev/pci/pcireg.h> 167#include <dev/pci/pcidevs.h> 168 169#define BKTR_DEBUG 170#ifdef BKTR_DEBUG 171int bktr_debug = 0; 172#define DPR(x) (bktr_debug ? printf x : 0) 173#else 174#define DPR(x) 175#endif 176#endif /* __NetBSD__ || __OpenBSD__ */ 177 178 179 180/****************************/ 181/* *** FreeBSD 4.x code *** */ 182/****************************/ 183#if (__FreeBSD_version >= 400000) 184 185static int bktr_probe( device_t dev ); 186static int bktr_attach( device_t dev ); 187static int bktr_detach( device_t dev ); 188static int bktr_shutdown( device_t dev ); 189static void bktr_intr(void *arg) { common_bktr_intr(arg); } 190 191static device_method_t bktr_methods[] = { 192 /* Device interface */ 193 DEVMETHOD(device_probe, bktr_probe), 194 DEVMETHOD(device_attach, bktr_attach), 195 DEVMETHOD(device_detach, bktr_detach), 196 DEVMETHOD(device_shutdown, bktr_shutdown), 197 198 { 0, 0 } 199}; 200 201static driver_t bktr_driver = { 202 "bktr", 203 bktr_methods, 204 sizeof(struct bktr_softc), 205}; 206 207static devclass_t bktr_devclass; 208 209static d_open_t bktr_open; 210static d_close_t bktr_close; 211static d_read_t bktr_read; 212static d_write_t bktr_write; 213static d_ioctl_t bktr_ioctl; 214static d_mmap_t bktr_mmap; 215static d_poll_t bktr_poll; 216 217#define CDEV_MAJOR 92 218static struct cdevsw bktr_cdevsw = { 219 /* open */ bktr_open, 220 /* close */ bktr_close, 221 /* read */ bktr_read, 222 /* write */ bktr_write, 223 /* ioctl */ bktr_ioctl, 224 /* poll */ bktr_poll, 225 /* mmap */ bktr_mmap, 226 /* strategy */ nostrategy, 227 /* name */ "bktr", 228 /* maj */ CDEV_MAJOR, 229 /* dump */ nodump, 230 /* psize */ nopsize, 231 /* flags */ 0, 232 /* bmaj */ -1 233}; 234 235DRIVER_MODULE(bktr, pci, bktr_driver, bktr_devclass, 0, 0); 236 237 238/* 239 * the boot time probe routine. 240 */ 241static int 242bktr_probe( device_t dev ) 243{ 244 unsigned int type = pci_get_devid(dev); 245 unsigned int rev = pci_get_revid(dev); 246 247 switch (type) { 248 case BROOKTREE_848_PCI_ID: 249 if (rev == 0x12) device_set_desc(dev, "BrookTree 848A"); 250 else device_set_desc(dev, "BrookTree 848"); 251 return 0; 252 case BROOKTREE_849_PCI_ID: 253 device_set_desc(dev, "BrookTree 849A"); 254 return 0; 255 case BROOKTREE_878_PCI_ID: 256 device_set_desc(dev, "BrookTree 878"); 257 return 0; 258 case BROOKTREE_879_PCI_ID: 259 device_set_desc(dev, "BrookTree 879"); 260 return 0; 261 }; 262 263 return ENXIO; 264} 265 266 267/* 268 * the attach routine. 269 */ 270static int 271bktr_attach( device_t dev ) 272{ 273 u_long latency; 274 u_long fun; 275 u_long val; 276 unsigned int rev; 277 unsigned int unit; 278 int error = 0; 279 int rid; 280#ifdef BROOKTREE_IRQ 281 u_long old_irq, new_irq; 282#endif 283 284 struct bktr_softc *bktr = device_get_softc(dev); 285 286 unit = device_get_unit(dev); 287 288 /* build the device name for bktr_name() */ 289 snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 290 291 /* 292 * Enable bus mastering and Memory Mapped device 293 */ 294 val = pci_read_config(dev, PCIR_COMMAND, 4); 295 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 296 pci_write_config(dev, PCIR_COMMAND, val, 4); 297 298 /* 299 * Map control/status registers. 300 */ 301 rid = PCIR_MAPS; 302 bktr->res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 303 0, ~0, 1, RF_ACTIVE); 304 305 if (!bktr->res_mem) { 306 device_printf(dev, "could not map memory\n"); 307 error = ENXIO; 308 goto fail; 309 } 310 bktr->memt = rman_get_bustag(bktr->res_mem); 311 bktr->memh = rman_get_bushandle(bktr->res_mem); 312 313 314 /* 315 * Disable the brooktree device 316 */ 317 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 318 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 319 320 321#ifdef BROOKTREE_IRQ /* from the configuration file */ 322 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 323 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 324 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 325 printf("bktr%d: attach: irq changed from %d to %d\n", 326 unit, (old_irq & 0xff), (new_irq & 0xff)); 327#endif 328 329 /* 330 * Allocate our interrupt. 331 */ 332 rid = 0; 333 bktr->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 334 RF_SHAREABLE | RF_ACTIVE); 335 if (bktr->res_irq == NULL) { 336 device_printf(dev, "could not map interrupt\n"); 337 error = ENXIO; 338 goto fail; 339 } 340 341 error = bus_setup_intr(dev, bktr->res_irq, INTR_TYPE_TTY, 342 bktr_intr, bktr, &bktr->res_ih); 343 if (error) { 344 device_printf(dev, "could not setup irq\n"); 345 goto fail; 346 347 } 348 349 350 /* Update the Device Control Register */ 351 /* on Bt878 and Bt879 cards */ 352 fun = pci_read_config( dev, 0x40, 2); 353 fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 354 355#if defined( BKTR_430_FX_MODE ) 356 if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 357 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 358#endif 359 360#if defined( BKTR_SIS_VIA_MODE ) 361 if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 362 fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 363 OPTi chipset motherboards too */ 364#endif 365 pci_write_config(dev, 0x40, fun, 2); 366 367 368 /* XXX call bt848_i2c dependent attach() routine */ 369#if (NSMBUS > 0) 370 if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc)) 371 printf("bktr%d: i2c_attach: can't attach\n", unit); 372#endif 373 374 375/* 376 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 377 * you have more than four, then 16 would probably be a better value. 378 */ 379#ifndef BROOKTREE_DEF_LATENCY_VALUE 380#define BROOKTREE_DEF_LATENCY_VALUE 10 381#endif 382 latency = pci_read_config(dev, PCI_LATENCY_TIMER, 4); 383 latency = (latency >> 8) & 0xff; 384 if ( bootverbose ) { 385 if (latency) 386 printf("brooktree%d: PCI bus latency is", unit); 387 else 388 printf("brooktree%d: PCI bus latency was 0 changing to", 389 unit); 390 } 391 if ( !latency ) { 392 latency = BROOKTREE_DEF_LATENCY_VALUE; 393 pci_write_config(dev, PCI_LATENCY_TIMER, latency<<8, 4); 394 } 395 if ( bootverbose ) { 396 printf(" %d.\n", (int) latency); 397 } 398 399 /* read the pci device id and revision id */ 400 fun = pci_get_devid(dev); 401 rev = pci_get_revid(dev); 402 403 /* call the common attach code */ 404 common_bktr_attach( bktr, unit, fun, rev ); 405 406 make_dev(&bktr_cdevsw, unit, 0, 0, 0444, "bktr%d", unit); 407 make_dev(&bktr_cdevsw, unit+16, 0, 0, 0444, "tuner%d", unit); 408 make_dev(&bktr_cdevsw, unit+32, 0, 0, 0444, "vbi%d", unit); 409 410 return 0; 411 412fail: 413 return error; 414 415} 416 417/* 418 * the detach routine. 419 */ 420static int 421bktr_detach( device_t dev ) 422{ 423 struct bktr_softc *bktr = device_get_softc(dev); 424 425 /* Disable the brooktree device */ 426 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 427 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 428 429 /* FIXME - Free memory for RISC programs, grab buffer, vbi buffers */ 430 431 /* 432 * Deallocate resources. 433 */ 434 bus_teardown_intr(dev, bktr->res_irq, bktr->res_ih); 435 bus_release_resource(dev, SYS_RES_IRQ, 0, bktr->res_irq); 436 bus_release_resource(dev, SYS_RES_MEMORY, PCIR_MAPS, bktr->res_mem); 437 438 return 0; 439} 440 441/* 442 * the shutdown routine. 443 */ 444static int 445bktr_shutdown( device_t dev ) 446{ 447 struct bktr_softc *bktr = device_get_softc(dev); 448 449 /* Disable the brooktree device */ 450 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 451 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 452 453 return 0; 454} 455 456 457/* 458 * Special Memory Allocation 459 */ 460vm_offset_t 461get_bktr_mem( int unit, unsigned size ) 462{ 463 vm_offset_t addr = 0; 464 465 addr = vm_page_alloc_contig(size, 0, 0xffffffff, 1<<24); 466 if (addr == 0) 467 addr = vm_page_alloc_contig(size, 0, 0xffffffff, PAGE_SIZE); 468 if (addr == 0) { 469 printf("bktr%d: Unable to allocate %d bytes of memory.\n", 470 unit, size); 471 } 472 473 return( addr ); 474} 475 476 477/*--------------------------------------------------------- 478** 479** BrookTree 848 character device driver routines 480** 481**--------------------------------------------------------- 482*/ 483 484#define VIDEO_DEV 0x00 485#define TUNER_DEV 0x01 486#define VBI_DEV 0x02 487 488#define UNIT(x) ((x) & 0x0f) 489#define FUNCTION(x) (x >> 4) 490 491/* 492 * 493 */ 494int 495bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) 496{ 497 bktr_ptr_t bktr; 498 int unit; 499 int result; 500 501 unit = UNIT( minor(dev) ); 502 503 /* Get the device data */ 504 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 505 if (bktr == NULL) { 506 /* the device is no longer valid/functioning */ 507 return (ENXIO); 508 } 509 510 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 511 return( ENXIO ); 512 513 /* Record that the device is now busy */ 514 device_busy(devclass_get_device(bktr_devclass, unit)); 515 516 517 if (bt848_card != -1) { 518 if ((bt848_card >> 8 == unit ) && 519 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 520 if ( bktr->bt848_card != (bt848_card & 0xff) ) { 521 bktr->bt848_card = (bt848_card & 0xff); 522 probeCard(bktr, FALSE, unit); 523 } 524 } 525 } 526 527 if (bt848_tuner != -1) { 528 if ((bt848_tuner >> 8 == unit ) && 529 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 530 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 531 bktr->bt848_tuner = (bt848_tuner & 0xff); 532 probeCard(bktr, FALSE, unit); 533 } 534 } 535 } 536 537 if (bt848_reverse_mute != -1) { 538 if ((bt848_reverse_mute >> 8) == unit ) { 539 bktr->reverse_mute = bt848_reverse_mute & 0xff; 540 } 541 } 542 543 if (bt848_slow_msp_audio != -1) { 544 if ((bt848_slow_msp_audio >> 8) == unit ) { 545 bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 546 } 547 } 548 549 switch ( FUNCTION( minor(dev) ) ) { 550 case VIDEO_DEV: 551 result = video_open( bktr ); 552 break; 553 case TUNER_DEV: 554 result = tuner_open( bktr ); 555 break; 556 case VBI_DEV: 557 result = vbi_open( bktr ); 558 break; 559 default: 560 result = ENXIO; 561 break; 562 } 563 564 /* If there was an error opening the device, undo the busy status */ 565 if (result != 0) 566 device_unbusy(devclass_get_device(bktr_devclass, unit)); 567 return( result ); 568} 569 570 571/* 572 * 573 */ 574int 575bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) 576{ 577 bktr_ptr_t bktr; 578 int unit; 579 int result; 580 581 unit = UNIT( minor(dev) ); 582 583 /* Get the device data */ 584 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 585 if (bktr == NULL) { 586 /* the device is no longer valid/functioning */ 587 return (ENXIO); 588 } 589 590 switch ( FUNCTION( minor(dev) ) ) { 591 case VIDEO_DEV: 592 result = video_close( bktr ); 593 break; 594 case TUNER_DEV: 595 result = tuner_close( bktr ); 596 break; 597 case VBI_DEV: 598 result = vbi_close( bktr ); 599 break; 600 default: 601 return (ENXIO); 602 break; 603 } 604 605 device_unbusy(devclass_get_device(bktr_devclass, unit)); 606 return( result ); 607} 608 609 610/* 611 * 612 */ 613int 614bktr_read( dev_t dev, struct uio *uio, int ioflag ) 615{ 616 bktr_ptr_t bktr; 617 int unit; 618 619 unit = UNIT(minor(dev)); 620 621 /* Get the device data */ 622 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 623 if (bktr == NULL) { 624 /* the device is no longer valid/functioning */ 625 return (ENXIO); 626 } 627 628 switch ( FUNCTION( minor(dev) ) ) { 629 case VIDEO_DEV: 630 return( video_read( bktr, unit, dev, uio ) ); 631 case VBI_DEV: 632 return( vbi_read( bktr, uio, ioflag ) ); 633 } 634 return( ENXIO ); 635} 636 637 638/* 639 * 640 */ 641int 642bktr_write( dev_t dev, struct uio *uio, int ioflag ) 643{ 644 return( EINVAL ); /* XXX or ENXIO ? */ 645} 646 647 648/* 649 * 650 */ 651int 652bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) 653{ 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, cmd, arg, pr ) ); 672 case TUNER_DEV: 673 return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); 674 } 675 676 return( ENXIO ); 677} 678 679 680/* 681 * 682 */ 683int 684bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 685{ 686 int unit; 687 bktr_ptr_t bktr; 688 689 unit = UNIT(minor(dev)); 690 691 if (FUNCTION(minor(dev)) > 0) /* only allow mmap on /dev/bktr[n] */ 692 return( -1 ); 693 694 /* Get the device data */ 695 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 696 if (bktr == NULL) { 697 /* the device is no longer valid/functioning */ 698 return (ENXIO); 699 } 700 701 if (nprot & PROT_EXEC) 702 return( -1 ); 703 704 if (offset < 0) 705 return( -1 ); 706 707 if (offset >= bktr->alloc_pages * PAGE_SIZE) 708 return( -1 ); 709 710 return( atop(vtophys(bktr->bigbuf) + offset) ); 711} 712 713int bktr_poll( dev_t dev, int events, struct proc *p) 714{ 715 int unit; 716 bktr_ptr_t bktr; 717 int revents = 0; 718 DECLARE_INTR_MASK(s); 719 720 unit = UNIT(minor(dev)); 721 722 /* Get the device data */ 723 bktr = (struct bktr_softc*)devclass_get_softc(bktr_devclass, unit); 724 if (bktr == NULL) { 725 /* the device is no longer valid/functioning */ 726 return (ENXIO); 727 } 728 729 DISABLE_INTR(s); 730 731 if (events & (POLLIN | POLLRDNORM)) { 732 733 switch ( FUNCTION( minor(dev) ) ) { 734 case VBI_DEV: 735 if(bktr->vbisize == 0) 736 selrecord(p, &bktr->vbi_select); 737 else 738 revents |= events & (POLLIN | POLLRDNORM); 739 break; 740 } 741 } 742 743 ENABLE_INTR(s); 744 745 return (revents); 746} 747 748#endif /* FreeBSD 4.x specific kernel interface routines */ 749 750/**********************************/ 751/* *** FreeBSD 2.2.x and 3.x *** */ 752/**********************************/ 753 754#if ((__FreeBSD__ == 2) || (__FreeBSD__ == 3)) 755 756static bktr_reg_t brooktree[ NBKTR ]; 757 758static const char* bktr_probe( pcici_t tag, pcidi_t type ); 759static void bktr_attach( pcici_t tag, int unit ); 760static void bktr_intr(void *arg) { common_bktr_intr(arg); } 761 762static u_long bktr_count; 763 764static struct pci_device bktr_device = { 765 "bktr", 766 bktr_probe, 767 bktr_attach, 768 &bktr_count 769}; 770 771DATA_SET (pcidevice_set, bktr_device); 772 773static d_open_t bktr_open; 774static d_close_t bktr_close; 775static d_read_t bktr_read; 776static d_write_t bktr_write; 777static d_ioctl_t bktr_ioctl; 778static d_mmap_t bktr_mmap; 779static d_poll_t bktr_poll; 780 781#define CDEV_MAJOR 92 782static struct cdevsw bktr_cdevsw = 783{ 784 bktr_open, bktr_close, bktr_read, bktr_write, 785 bktr_ioctl, nostop, nullreset, nodevtotty, 786 bktr_poll, bktr_mmap, NULL, "bktr", 787 NULL, -1 788}; 789 790static int bktr_devsw_installed; 791 792static void 793bktr_drvinit( void *unused ) 794{ 795 dev_t dev; 796 797 if ( ! bktr_devsw_installed ) { 798 dev = makedev(CDEV_MAJOR, 0); 799 cdevsw_add(&dev,&bktr_cdevsw, NULL); 800 bktr_devsw_installed = 1; 801 } 802} 803 804SYSINIT(bktrdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bktr_drvinit,NULL) 805 806/* 807 * the boot time probe routine. 808 */ 809static const char* 810bktr_probe( pcici_t tag, pcidi_t type ) 811{ 812 unsigned int rev = pci_conf_read( tag, PCIR_REVID) & 0x000000ff; 813 814 switch (type) { 815 case BROOKTREE_848_PCI_ID: 816 if (rev == 0x12) return("BrookTree 848A"); 817 else return("BrookTree 848"); 818 case BROOKTREE_849_PCI_ID: 819 return("BrookTree 849A"); 820 case BROOKTREE_878_PCI_ID: 821 return("BrookTree 878"); 822 case BROOKTREE_879_PCI_ID: 823 return("BrookTree 879"); 824 }; 825 826 return ((char *)0); 827} 828 829/* 830 * the attach routine. 831 */ 832static void 833bktr_attach( pcici_t tag, int unit ) 834{ 835 bktr_ptr_t bktr; 836 u_long latency; 837 u_long fun; 838 unsigned int rev; 839 unsigned long base; 840#ifdef BROOKTREE_IRQ 841 u_long old_irq, new_irq; 842#endif 843 844 bktr = &brooktree[unit]; 845 846 if (unit >= NBKTR) { 847 printf("brooktree%d: attach: only %d units configured.\n", 848 unit, NBKTR); 849 printf("brooktree%d: attach: invalid unit number.\n", unit); 850 return; 851 } 852 853 /* build the device name for bktr_name() */ 854 snprintf(bktr->bktr_xname, sizeof(bktr->bktr_xname), "bktr%d",unit); 855 856 /* Enable Memory Mapping */ 857 fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 858 pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 2); 859 860 /* Enable Bus Mastering */ 861 fun = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); 862 pci_conf_write(tag, PCI_COMMAND_STATUS_REG, fun | 4); 863 864 bktr->tag = tag; 865 866 867 /* 868 * Map control/status registers 869 */ 870 pci_map_mem( tag, PCI_MAP_REG_START, (vm_offset_t *) &base, 871 &bktr->phys_base ); 872#if (__FreeBSD_version >= 300000) 873 bktr->memt = I386_BUS_SPACE_MEM; /* XXX should use proper bus space */ 874 bktr->memh = (bus_space_handle_t)base; /* XXX functions here */ 875#endif 876 877 /* 878 * Disable the brooktree device 879 */ 880 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 881 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 882 883#ifdef BROOKTREE_IRQ /* from the configuration file */ 884 old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 885 pci_conf_write(tag, PCI_INTERRUPT_REG, BROOKTREE_IRQ); 886 new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); 887 printf("bktr%d: attach: irq changed from %d to %d\n", 888 unit, (old_irq & 0xff), (new_irq & 0xff)); 889#endif 890 891 /* 892 * setup the interrupt handling routine 893 */ 894 pci_map_int(tag, bktr_intr, (void*) bktr, &tty_imask); 895 896 897 /* Update the Device Control Register */ 898 /* on Bt878 and Bt879 cards */ 899 fun = pci_conf_read(tag, 0x40); 900 fun = fun | 1; /* Enable writes to the sub-system vendor ID */ 901 902#if defined( BKTR_430_FX_MODE ) 903 if (bootverbose) printf("Using 430 FX chipset compatibilty mode\n"); 904 fun = fun | 2; /* Enable Intel 430 FX compatibility mode */ 905#endif 906 907#if defined( BKTR_SIS_VIA_MODE ) 908 if (bootverbose) printf("Using SiS/VIA chipset compatibilty mode\n"); 909 fun = fun | 4; /* Enable SiS/VIA compatibility mode (usefull for 910 OPTi chipset motherboards too */ 911#endif 912 pci_conf_write(tag, 0x40, fun); 913 914 915 /* XXX call bt848_i2c dependent attach() routine */ 916#if (NSMBUS > 0) 917 if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc)) 918 printf("bktr%d: i2c_attach: can't attach\n", unit); 919#endif 920 921 922/* 923 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 924 * you have more than four, then 16 would probably be a better value. 925 */ 926#ifndef BROOKTREE_DEF_LATENCY_VALUE 927#define BROOKTREE_DEF_LATENCY_VALUE 10 928#endif 929 latency = pci_conf_read(tag, PCI_LATENCY_TIMER); 930 latency = (latency >> 8) & 0xff; 931 if ( bootverbose ) { 932 if (latency) 933 printf("brooktree%d: PCI bus latency is", unit); 934 else 935 printf("brooktree%d: PCI bus latency was 0 changing to", 936 unit); 937 } 938 if ( !latency ) { 939 latency = BROOKTREE_DEF_LATENCY_VALUE; 940 pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); 941 } 942 if ( bootverbose ) { 943 printf(" %d.\n", (int) latency); 944 } 945 946 947 /* read the pci device id and revision id */ 948 fun = pci_conf_read(tag, PCI_ID_REG); 949 rev = pci_conf_read(tag, PCIR_REVID) & 0x000000ff; 950 951 /* call the common attach code */ 952 common_bktr_attach( bktr, unit, fun, rev ); 953 954#ifdef DEVFS 955 /* XXX This just throw away the token, which should probably be fixed when 956 DEVFS is finally made really operational. */ 957 devfs_add_devswf(&bktr_cdevsw, unit, DV_CHR, 0, 0, 0444, "bktr%d", unit); 958 devfs_add_devswf(&bktr_cdevsw, unit+16, DV_CHR, 0, 0, 0444, "tuner%d", unit); 959 devfs_add_devswf(&bktr_cdevsw, unit+32, DV_CHR, 0, 0, 0444, "vbi%d", unit); 960#endif /* DEVFS */ 961 962} 963 964 965/* 966 * Special Memory Allocation 967 */ 968vm_offset_t 969get_bktr_mem( int unit, unsigned size ) 970{ 971 vm_offset_t addr = 0; 972 973 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24); 974 if (addr == 0) 975 addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 976 PAGE_SIZE); 977 if (addr == 0) { 978 printf("bktr%d: Unable to allocate %d bytes of memory.\n", 979 unit, size); 980 } 981 982 return( addr ); 983} 984 985/*--------------------------------------------------------- 986** 987** BrookTree 848 character device driver routines 988** 989**--------------------------------------------------------- 990*/ 991 992 993#define VIDEO_DEV 0x00 994#define TUNER_DEV 0x01 995#define VBI_DEV 0x02 996 997#define UNIT(x) ((x) & 0x0f) 998#define FUNCTION(x) ((x >> 4) & 0x0f) 999 1000 1001/* 1002 * 1003 */ 1004int 1005bktr_open( dev_t dev, int flags, int fmt, struct proc *p ) 1006{ 1007 bktr_ptr_t bktr; 1008 int unit; 1009 1010 unit = UNIT( minor(dev) ); 1011 if (unit >= NBKTR) /* unit out of range */ 1012 return( ENXIO ); 1013 1014 bktr = &(brooktree[ unit ]); 1015 1016 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 1017 return( ENXIO ); 1018 1019 1020 if (bt848_card != -1) { 1021 if ((bt848_card >> 8 == unit ) && 1022 ( (bt848_card & 0xff) < Bt848_MAX_CARD )) { 1023 if ( bktr->bt848_card != (bt848_card & 0xff) ) { 1024 bktr->bt848_card = (bt848_card & 0xff); 1025 probeCard(bktr, FALSE, unit); 1026 } 1027 } 1028 } 1029 1030 if (bt848_tuner != -1) { 1031 if ((bt848_tuner >> 8 == unit ) && 1032 ( (bt848_tuner & 0xff) < Bt848_MAX_TUNER )) { 1033 if ( bktr->bt848_tuner != (bt848_tuner & 0xff) ) { 1034 bktr->bt848_tuner = (bt848_tuner & 0xff); 1035 probeCard(bktr, FALSE, unit); 1036 } 1037 } 1038 } 1039 1040 if (bt848_reverse_mute != -1) { 1041 if ((bt848_reverse_mute >> 8) == unit ) { 1042 bktr->reverse_mute = bt848_reverse_mute & 0xff; 1043 } 1044 } 1045 1046 if (bt848_slow_msp_audio != -1) { 1047 if ((bt848_slow_msp_audio >> 8) == unit ) { 1048 bktr->slow_msp_audio = (bt848_slow_msp_audio & 0xff); 1049 } 1050 } 1051 1052 switch ( FUNCTION( minor(dev) ) ) { 1053 case VIDEO_DEV: 1054 return( video_open( bktr ) ); 1055 case TUNER_DEV: 1056 return( tuner_open( bktr ) ); 1057 case VBI_DEV: 1058 return( vbi_open( bktr ) ); 1059 } 1060 return( ENXIO ); 1061} 1062 1063 1064/* 1065 * 1066 */ 1067int 1068bktr_close( dev_t dev, int flags, int fmt, struct proc *p ) 1069{ 1070 bktr_ptr_t bktr; 1071 int unit; 1072 1073 unit = UNIT( minor(dev) ); 1074 if (unit >= NBKTR) /* unit out of range */ 1075 return( ENXIO ); 1076 1077 bktr = &(brooktree[ unit ]); 1078 1079 switch ( FUNCTION( minor(dev) ) ) { 1080 case VIDEO_DEV: 1081 return( video_close( bktr ) ); 1082 case TUNER_DEV: 1083 return( tuner_close( bktr ) ); 1084 case VBI_DEV: 1085 return( vbi_close( bktr ) ); 1086 } 1087 1088 return( ENXIO ); 1089} 1090 1091/* 1092 * 1093 */ 1094int 1095bktr_read( dev_t dev, struct uio *uio, int ioflag ) 1096{ 1097 bktr_ptr_t bktr; 1098 int unit; 1099 1100 unit = UNIT(minor(dev)); 1101 if (unit >= NBKTR) /* unit out of range */ 1102 return( ENXIO ); 1103 1104 bktr = &(brooktree[unit]); 1105 1106 switch ( FUNCTION( minor(dev) ) ) { 1107 case VIDEO_DEV: 1108 return( video_read( bktr, unit, dev, uio ) ); 1109 case VBI_DEV: 1110 return( vbi_read( bktr, uio, ioflag ) ); 1111 } 1112 return( ENXIO ); 1113} 1114 1115 1116/* 1117 * 1118 */ 1119int 1120bktr_write( dev_t dev, struct uio *uio, int ioflag ) 1121{ 1122 return( EINVAL ); /* XXX or ENXIO ? */ 1123} 1124 1125/* 1126 * 1127 */ 1128int 1129bktr_ioctl( dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr ) 1130{ 1131 bktr_ptr_t bktr; 1132 int unit; 1133 1134 unit = UNIT(minor(dev)); 1135 if (unit >= NBKTR) /* unit out of range */ 1136 return( ENXIO ); 1137 1138 bktr = &(brooktree[ unit ]); 1139 1140 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 1141 return( ENOMEM ); 1142 1143 switch ( FUNCTION( minor(dev) ) ) { 1144 case VIDEO_DEV: 1145 return( video_ioctl( bktr, unit, cmd, arg, pr ) ); 1146 case TUNER_DEV: 1147 return( tuner_ioctl( bktr, unit, cmd, arg, pr ) ); 1148 } 1149 1150 return( ENXIO ); 1151} 1152 1153/* 1154 * bktr_mmap. 1155 * Note: 2.2.5/2.2.6/2.2.7/3.0 users must manually 1156 * edit the line below and change "vm_offset_t" to "int" 1157 */ 1158int bktr_mmap( dev_t dev, vm_offset_t offset, int nprot ) 1159 1160{ 1161 int unit; 1162 bktr_ptr_t bktr; 1163 1164 unit = UNIT(minor(dev)); 1165 1166 if (unit >= NBKTR || FUNCTION(minor(dev)) > 0) 1167 return( -1 ); 1168 1169 bktr = &(brooktree[ unit ]); 1170 1171 if (nprot & PROT_EXEC) 1172 return( -1 ); 1173 1174 if (offset < 0) 1175 return( -1 ); 1176 1177 if (offset >= bktr->alloc_pages * PAGE_SIZE) 1178 return( -1 ); 1179 1180 return( i386_btop(vtophys(bktr->bigbuf) + offset) ); 1181} 1182 1183int bktr_poll( dev_t dev, int events, struct proc *p) 1184{ 1185 int unit; 1186 bktr_ptr_t bktr; 1187 int revents = 0; 1188 1189 unit = UNIT(minor(dev)); 1190 1191 if (unit >= NBKTR) 1192 return( -1 ); 1193 1194 bktr = &(brooktree[ unit ]); 1195 1196 disable_intr(); 1197 1198 if (events & (POLLIN | POLLRDNORM)) { 1199 1200 switch ( FUNCTION( minor(dev) ) ) { 1201 case VBI_DEV: 1202 if(bktr->vbisize == 0) 1203 selrecord(p, &bktr->vbi_select); 1204 else 1205 revents |= events & (POLLIN | POLLRDNORM); 1206 break; 1207 } 1208 } 1209 1210 enable_intr(); 1211 1212 return (revents); 1213} 1214 1215 1216#endif /* FreeBSD 2.2.x and 3.x specific kernel interface routines */ 1217 1218 1219/*****************/ 1220/* *** BSDI *** */ 1221/*****************/ 1222 1223#if defined(__bsdi__) 1224#endif /* __bsdi__ BSDI specific kernel interface routines */ 1225 1226 1227/*****************************/ 1228/* *** OpenBSD / NetBSD *** */ 1229/*****************************/ 1230#if defined(__NetBSD__) || defined(__OpenBSD__) 1231 1232#define IPL_VIDEO IPL_BIO /* XXX */ 1233 1234static int bktr_intr(void *arg) { return common_bktr_intr(arg); } 1235 1236#define bktr_open bktropen 1237#define bktr_close bktrclose 1238#define bktr_read bktrread 1239#define bktr_write bktrwrite 1240#define bktr_ioctl bktrioctl 1241#define bktr_mmap bktrmmap 1242 1243int bktr_open __P((dev_t, int, int, struct proc *)); 1244int bktr_close __P((dev_t, int, int, struct proc *)); 1245int bktr_read __P((dev_t, struct uio *, int)); 1246int bktr_write __P((dev_t, struct uio *, int)); 1247int bktr_ioctl __P((dev_t, ioctl_cmd_t, caddr_t, int, struct proc*)); 1248int bktr_mmap __P((dev_t, int, int)); 1249 1250vm_offset_t vm_page_alloc_contig(vm_offset_t, vm_offset_t, 1251 vm_offset_t, vm_offset_t); 1252 1253#if defined(__OpenBSD__) 1254static int bktr_probe __P((struct device *, void *, void *)); 1255#else 1256static int bktr_probe __P((struct device *, struct cfdata *, void *)); 1257#endif 1258static void bktr_attach __P((struct device *, struct device *, void *)); 1259 1260struct cfattach bktr_ca = { 1261 sizeof(struct bktr_softc), bktr_probe, bktr_attach 1262}; 1263 1264#if defined(__NetBSD__) 1265extern struct cfdriver bktr_cd; 1266#else 1267struct cfdriver bktr_cd = { 1268 NULL, "bktr", DV_DULL 1269}; 1270#endif 1271 1272int 1273bktr_probe(parent, match, aux) 1274 struct device *parent; 1275#if defined(__OpenBSD__) 1276 void *match; 1277#else 1278 struct cfdata *match; 1279#endif 1280 void *aux; 1281{ 1282 struct pci_attach_args *pa = aux; 1283 1284 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_BROOKTREE && 1285 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT848 || 1286 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT849 || 1287 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT878 || 1288 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_BROOKTREE_BT879)) 1289 return 1; 1290 1291 return 0; 1292} 1293 1294 1295/* 1296 * the attach routine. 1297 */ 1298static void 1299bktr_attach(struct device *parent, struct device *self, void *aux) 1300{ 1301 bktr_ptr_t bktr; 1302 u_long latency; 1303 u_long fun; 1304 unsigned int rev; 1305 1306#if defined(__OpenBSD__) 1307 struct pci_attach_args *pa = aux; 1308 pci_chipset_tag_t pc = pa->pa_pc; 1309 1310 pci_intr_handle_t ih; 1311 const char *intrstr; 1312 int retval; 1313 int unit; 1314 1315 bktr = (bktr_ptr_t)self; 1316 unit = bktr->bktr_dev.dv_unit; 1317 1318 bktr->pc = pa->pa_pc; 1319 bktr->tag = pa->pa_tag; 1320 bktr->dmat = pa->pa_dmat; 1321 1322 /* 1323 * map memory 1324 */ 1325 bktr->memt = pa->pa_memt; 1326 retval = pci_mem_find(pc, pa->pa_tag, PCI_MAPREG_START, 1327 &bktr->phys_base, &bktr->obmemsz, NULL); 1328 if (!retval) 1329 retval = bus_space_map(pa->pa_memt, bktr->phys_base, 1330 bktr->obmemsz, 0, &bktr->memh); 1331 if (retval) { 1332 printf(": couldn't map memory\n"); 1333 return; 1334 } 1335 1336 1337 /* 1338 * map interrupt 1339 */ 1340 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 1341 pa->pa_intrline, &ih)) { 1342 printf(": couldn't map interrupt\n"); 1343 return; 1344 } 1345 intrstr = pci_intr_string(pa->pa_pc, ih); 1346 1347 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 1348 bktr_intr, bktr, bktr->bktr_dev.dv_xname); 1349 if (bktr->ih == NULL) { 1350 printf(": couldn't establish interrupt"); 1351 if (intrstr != NULL) 1352 printf(" at %s", intrstr); 1353 printf("\n"); 1354 return; 1355 } 1356 1357 if (intrstr != NULL) 1358 printf(": %s\n", intrstr); 1359#endif /* __OpenBSD__ */ 1360 1361#if defined(__NetBSD__) 1362 struct pci_attach_args *pa = aux; 1363 pci_intr_handle_t ih; 1364 const char *intrstr; 1365 int retval; 1366 int unit; 1367 1368 bktr = (bktr_ptr_t)self; 1369 unit = bktr->bktr_dev.dv_unit; 1370 bktr->dmat = pa->pa_dmat; 1371 1372 printf("\n"); 1373 1374 /* 1375 * map memory 1376 */ 1377 retval = pci_mapreg_map(pa, PCI_MAPREG_START, 1378 PCI_MAPREG_TYPE_MEM 1379 | PCI_MAPREG_MEM_TYPE_32BIT, 0, 1380 &bktr->memt, &bktr->memh, NULL, 1381 &bktr->obmemsz); 1382 DPR(("pci_mapreg_map: memt %x, memh %x, size %x\n", 1383 bktr->memt, (u_int)bktr->memh, (u_int)bktr->obmemsz)); 1384 if (retval) { 1385 printf("%s: couldn't map memory\n", bktr_name(bktr)); 1386 return; 1387 } 1388 1389 /* 1390 * Disable the brooktree device 1391 */ 1392 OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); 1393 OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); 1394 1395 /* 1396 * map interrupt 1397 */ 1398 if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin, 1399 pa->pa_intrline, &ih)) { 1400 printf("%s: couldn't map interrupt\n", 1401 bktr_name(bktr)); 1402 return; 1403 } 1404 intrstr = pci_intr_string(pa->pa_pc, ih); 1405 bktr->ih = pci_intr_establish(pa->pa_pc, ih, IPL_VIDEO, 1406 bktr_intr, bktr); 1407 if (bktr->ih == NULL) { 1408 printf("%s: couldn't establish interrupt", 1409 bktr_name(bktr)); 1410 if (intrstr != NULL) 1411 printf(" at %s", intrstr); 1412 printf("\n"); 1413 return; 1414 } 1415 if (intrstr != NULL) 1416 printf("%s: interrupting at %s\n", bktr_name(bktr), 1417 intrstr); 1418#endif /* __NetBSD__ */ 1419 1420/* 1421 * PCI latency timer. 32 is a good value for 4 bus mastering slots, if 1422 * you have more than four, then 16 would probably be a better value. 1423 */ 1424#ifndef BROOKTREE_DEF_LATENCY_VALUE 1425#define BROOKTREE_DEF_LATENCY_VALUE 10 1426#endif 1427 latency = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_LATENCY_TIMER); 1428 latency = (latency >> 8) & 0xff; 1429 1430 if (!latency) { 1431 if (bootverbose) { 1432 printf("%s: PCI bus latency was 0 changing to %d", 1433 bktr_name(bktr), BROOKTREE_DEF_LATENCY_VALUE); 1434 } 1435 latency = BROOKTREE_DEF_LATENCY_VALUE; 1436 pci_conf_write(pa->pa_pc, pa->pa_tag, 1437 PCI_LATENCY_TIMER, latency<<8); 1438 } 1439 1440 1441 /* Enabled Bus Master 1442 XXX: check if all old DMA is stopped first (e.g. after warm 1443 boot) */ 1444 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1445 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 1446 fun | PCI_COMMAND_MASTER_ENABLE); 1447 1448 /* read the pci id and determine the card type */ 1449 fun = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 1450 rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0x000000ff; 1451 1452 common_bktr_attach(bktr, unit, fun, rev); 1453} 1454 1455 1456/* 1457 * Special Memory Allocation 1458 */ 1459vm_offset_t 1460get_bktr_mem(bktr, dmapp, size) 1461 bktr_ptr_t bktr; 1462 bus_dmamap_t *dmapp; 1463 unsigned int size; 1464{ 1465 bus_dma_tag_t dmat = bktr->dmat; 1466 bus_dma_segment_t seg; 1467 bus_size_t align; 1468 int rseg; 1469 caddr_t kva; 1470 1471 /* 1472 * Allocate a DMA area 1473 */ 1474 align = 1 << 24; 1475 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1476 &rseg, BUS_DMA_NOWAIT)) { 1477 align = PAGE_SIZE; 1478 if (bus_dmamem_alloc(dmat, size, align, 0, &seg, 1, 1479 &rseg, BUS_DMA_NOWAIT)) { 1480 printf("%s: Unable to dmamem_alloc of %d bytes\n", 1481 bktr_name(bktr), size); 1482 return 0; 1483 } 1484 } 1485 if (bus_dmamem_map(dmat, &seg, rseg, size, 1486 &kva, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) { 1487 printf("%s: Unable to dmamem_map of %d bytes\n", 1488 bktr_name(bktr), size); 1489 bus_dmamem_free(dmat, &seg, rseg); 1490 return 0; 1491 } 1492#ifdef __OpenBSD__ 1493 bktr->dm_mapsize = size; 1494#endif 1495 /* 1496 * Create and locd the DMA map for the DMA area 1497 */ 1498 if (bus_dmamap_create(dmat, size, 1, size, 0, BUS_DMA_NOWAIT, dmapp)) { 1499 printf("%s: Unable to dmamap_create of %d bytes\n", 1500 bktr_name(bktr), size); 1501 bus_dmamem_unmap(dmat, kva, size); 1502 bus_dmamem_free(dmat, &seg, rseg); 1503 return 0; 1504 } 1505 if (bus_dmamap_load(dmat, *dmapp, kva, size, NULL, BUS_DMA_NOWAIT)) { 1506 printf("%s: Unable to dmamap_load of %d bytes\n", 1507 bktr_name(bktr), size); 1508 bus_dmamem_unmap(dmat, kva, size); 1509 bus_dmamem_free(dmat, &seg, rseg); 1510 bus_dmamap_destroy(dmat, *dmapp); 1511 return 0; 1512 } 1513 return (vm_offset_t)kva; 1514} 1515 1516void 1517free_bktr_mem(bktr, dmap, kva) 1518 bktr_ptr_t bktr; 1519 bus_dmamap_t dmap; 1520 vm_offset_t kva; 1521{ 1522 bus_dma_tag_t dmat = bktr->dmat; 1523 1524#ifdef __NetBSD__ 1525 bus_dmamem_unmap(dmat, (caddr_t)kva, dmap->dm_mapsize); 1526#else 1527 bus_dmamem_unmap(dmat, (caddr_t)kva, bktr->dm_mapsize); 1528#endif 1529 bus_dmamem_free(dmat, dmap->dm_segs, 1); 1530 bus_dmamap_destroy(dmat, dmap); 1531} 1532 1533 1534/*--------------------------------------------------------- 1535** 1536** BrookTree 848 character device driver routines 1537** 1538**--------------------------------------------------------- 1539*/ 1540 1541 1542#define VIDEO_DEV 0x00 1543#define TUNER_DEV 0x01 1544#define VBI_DEV 0x02 1545 1546#define UNIT(x) (minor((x) & 0x0f)) 1547#define FUNCTION(x) (minor((x >> 4) & 0x0f)) 1548 1549/* 1550 * 1551 */ 1552int 1553bktr_open(dev_t dev, int flags, int fmt, struct proc *p) 1554{ 1555 bktr_ptr_t bktr; 1556 int unit; 1557 1558 unit = UNIT(dev); 1559 1560 /* unit out of range */ 1561 if ((unit > bktr_cd.cd_ndevs) || (bktr_cd.cd_devs[unit] == NULL)) 1562 return(ENXIO); 1563 1564 bktr = bktr_cd.cd_devs[unit]; 1565 1566 if (!(bktr->flags & METEOR_INITALIZED)) /* device not found */ 1567 return(ENXIO); 1568 1569 switch (FUNCTION(dev)) { 1570 case VIDEO_DEV: 1571 return(video_open(bktr)); 1572 case TUNER_DEV: 1573 return(tuner_open(bktr)); 1574 case VBI_DEV: 1575 return(vbi_open(bktr)); 1576 } 1577 1578 return(ENXIO); 1579} 1580 1581 1582/* 1583 * 1584 */ 1585int 1586bktr_close(dev_t dev, int flags, int fmt, struct proc *p) 1587{ 1588 bktr_ptr_t bktr; 1589 int unit; 1590 1591 unit = UNIT(dev); 1592 1593 bktr = bktr_cd.cd_devs[unit]; 1594 1595 switch (FUNCTION(dev)) { 1596 case VIDEO_DEV: 1597 return(video_close(bktr)); 1598 case TUNER_DEV: 1599 return(tuner_close(bktr)); 1600 case VBI_DEV: 1601 return(vbi_close(bktr)); 1602 } 1603 1604 return(ENXIO); 1605} 1606 1607/* 1608 * 1609 */ 1610int 1611bktr_read(dev_t dev, struct uio *uio, int ioflag) 1612{ 1613 bktr_ptr_t bktr; 1614 int unit; 1615 1616 unit = UNIT(dev); 1617 1618 bktr = bktr_cd.cd_devs[unit]; 1619 1620 switch (FUNCTION(dev)) { 1621 case VIDEO_DEV: 1622 return(video_read(bktr, unit, dev, uio)); 1623 case VBI_DEV: 1624 return(vbi_read(bktr, uio, ioflag)); 1625 } 1626 1627 return(ENXIO); 1628} 1629 1630 1631/* 1632 * 1633 */ 1634int 1635bktr_write(dev_t dev, struct uio *uio, int ioflag) 1636{ 1637 /* operation not supported */ 1638 return(EOPNOTSUPP); 1639} 1640 1641/* 1642 * 1643 */ 1644int 1645bktr_ioctl(dev_t dev, ioctl_cmd_t cmd, caddr_t arg, int flag, struct proc* pr) 1646{ 1647 bktr_ptr_t bktr; 1648 int unit; 1649 1650 unit = UNIT(dev); 1651 1652 bktr = bktr_cd.cd_devs[unit]; 1653 1654 if (bktr->bigbuf == 0) /* no frame buffer allocated (ioctl failed) */ 1655 return(ENOMEM); 1656 1657 switch (FUNCTION(dev)) { 1658 case VIDEO_DEV: 1659 return(video_ioctl(bktr, unit, cmd, arg, pr)); 1660 case TUNER_DEV: 1661 return(tuner_ioctl(bktr, unit, cmd, arg, pr)); 1662 } 1663 1664 return(ENXIO); 1665} 1666 1667/* 1668 * 1669 */ 1670int 1671bktr_mmap(dev_t dev, int offset, int nprot) 1672{ 1673 int unit; 1674 bktr_ptr_t bktr; 1675 1676 unit = UNIT(dev); 1677 1678 if (FUNCTION(dev) > 0) /* only allow mmap on /dev/bktr[n] */ 1679 return(-1); 1680 1681 bktr = bktr_cd.cd_devs[unit]; 1682 1683 if ((vaddr_t)offset < 0) 1684 return(-1); 1685 1686 if ((vaddr_t)offset >= bktr->alloc_pages * PAGE_SIZE) 1687 return(-1); 1688 1689#ifdef __NetBSD__ 1690 return (bus_dmamem_mmap(bktr->dmat, bktr->dm_mem->dm_segs, 1, 1691 (vaddr_t)offset, nprot, BUS_DMA_WAITOK)); 1692#else 1693 return(i386_btop(vtophys(bktr->bigbuf) + offset)); 1694#endif 1695} 1696 1697#endif /* __NetBSD__ || __OpenBSD__ */ 1698