Print this page
6973 audioens driver does not work on VMWare
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: TBD

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/audio/drv/audioens/audioens.c
          +++ new/usr/src/uts/common/io/audio/drv/audioens/audioens.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
       23 + * Copyright 2016 Garrett D'Amore <garrett@damore.org>
  23   24   */
  24   25  /*
  25   26   * Purpose: Creative/Ensoniq AudioPCI97  driver (ES1371/ES1373)
  26   27   *
  27   28   * This driver is used with the original Ensoniq AudioPCI97 card and many
  28   29   * PCI based Sound Blaster cards by Creative Technologies. For example
  29   30   * Sound Blaster PCI128 and Creative/Ectiva EV1938.
  30   31   */
  31   32  
  32   33  /*
↓ open down ↓ 3 lines elided ↑ open up ↑
  36   37   *
  37   38   * This software is released under CDDL 1.0 source license.
  38   39   * See the COPYING file included in the main directory of this source
  39   40   * distribution for the license terms and conditions.
  40   41   */
  41   42  
  42   43  #include <sys/audio/audio_driver.h>
  43   44  #include <sys/audio/ac97.h>
  44   45  #include <sys/note.h>
  45   46  #include <sys/pci.h>
       47 +
       48 +/*
       49 + * For VMWare platforms, we have to utilize the (emulated) hardware interrupts
       50 + * of the device.  This is necessary for audio playback to function, as
       51 + * the toggling of the interrupt bits apparently triggers logic inside the
       52 + * emulated device.  So we need to detect this platform, and conditionally
       53 + * wire up the interrupt handler.
       54 + */
       55 +#ifdef __x86
       56 +#include <sys/x86_archext.h>
       57 +#endif
       58 +
  46   59  #include "audioens.h"
  47   60  
  48   61  /*
  49   62   * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit
  50   63   * garbled audio in some cases and setting the latency to higer values fixes it
  51   64   * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios)
  52   65   */
  53   66  int audioens_latency = 0;
  54   67  
  55   68  /*
↓ open down ↓ 32 lines elided ↑ open up ↑
  88  101  #define PORT_DAC                0
  89  102  #define PORT_ADC                1
  90  103  #define PORT_MAX                PORT_ADC
  91  104  
  92  105          caddr_t                 kaddr;
  93  106          uint32_t                paddr;
  94  107          ddi_acc_handle_t        acch;
  95  108          ddi_dma_handle_t        dmah;
  96  109          int                     nchan;
  97  110          unsigned                nframes;
      111 +        unsigned                iframes;
  98  112          unsigned                frameno;
  99  113          uint64_t                count;
 100  114  
 101  115          struct audioens_dev     *dev;
 102      -        audio_engine_t  *engine;
      116 +        audio_engine_t          *engine;
 103  117  } audioens_port_t;
 104  118  
 105  119  typedef struct audioens_dev
 106  120  {
 107  121          audio_dev_t             *osdev;
 108  122          kmutex_t                mutex;
 109  123          uint16_t                devid;
 110  124          uint8_t                 revision;
 111  125          dev_info_t              *dip;
 112  126  
 113  127          audioens_port_t         port[PORT_MAX + 1];
 114  128  
 115  129          ac97_t                  *ac97;
 116  130  
 117  131          caddr_t                 regs;
 118  132          ddi_acc_handle_t        acch;
      133 +
      134 +        boolean_t               suspended;
      135 +
      136 +#ifdef __x86
      137 +        boolean_t               useintr;
      138 +        ddi_intr_handle_t       intrh;
      139 +        uint_t                  intrpri;
      140 +#endif
 119  141  } audioens_dev_t;
 120  142  
 121  143  static ddi_device_acc_attr_t acc_attr = {
 122  144          DDI_DEVICE_ATTR_V0,
 123  145          DDI_STRUCTURE_LE_ACC,
 124  146          DDI_STRICTORDER_ACC
 125  147  };
 126  148  
 127  149  static ddi_device_acc_attr_t buf_attr = {
 128  150          DDI_DEVICE_ATTR_V0,
 129  151          DDI_NEVERSWAP_ACC,
 130  152          DDI_STRICTORDER_ACC
 131  153  };
 132  154  
 133      -/*
 134      - * The hardware appears to be able to address up to 16-bits worth of longwords,
 135      - * giving a total address space of 256K.  But we need substantially less.
 136      - */
 137      -#define AUDIOENS_BUF_LEN        (16384)
 138      -
 139  155  static ddi_dma_attr_t dma_attr = {
 140  156          DMA_ATTR_VERSION,       /* dma_attr_version */
 141  157          0x0,                    /* dma_attr_addr_lo */
 142  158          0xffffffffU,            /* dma_attr_addr_hi */
 143  159          0x3ffff,                /* dma_attr_count_max */
 144  160          0x8,                    /* dma_attr_align */
 145  161          0x7f,                   /* dma_attr_burstsizes */
 146  162          0x1,                    /* dma_attr_minxfer */
 147  163          0x3ffff,                /* dma_attr_maxxfer */
 148  164          0x3ffff,                /* dma_attr_seg */
↓ open down ↓ 233 lines elided ↑ open up ↑
 382  398          PUT32(dev, offs, data);
 383  399  }
 384  400  
 385  401  static uint32_t
 386  402  audioens_readmem(audioens_dev_t *dev, uint32_t page, uint32_t offs)
 387  403  {
 388  404          PUT32(dev, CONC_bMEMPAGE_OFF, page);    /* Select memory page */
 389  405          return (GET32(dev, offs));
 390  406  }
 391  407  
      408 +#ifdef __x86
      409 +static unsigned
      410 +audioens_intr(caddr_t arg1, caddr_t arg2)
      411 +{
      412 +        audioens_dev_t *dev = (void *)arg1;
      413 +        uint32_t status;
      414 +        uint32_t frameno;
      415 +        uint32_t n;
      416 +        audioens_port_t *port;
      417 +
      418 +        _NOTE(ARGUNUSED(arg2));
      419 +
      420 +        mutex_enter(&dev->mutex);
      421 +        if (dev->suspended || !dev->useintr) {
      422 +                mutex_exit(&dev->mutex);
      423 +                return (DDI_INTR_UNCLAIMED);
      424 +        }
      425 +
      426 +        status = GET32(dev, CONC_dSTATUS_OFF);
      427 +        if ((status & CONC_STATUS_PENDING) == 0) {
      428 +                mutex_exit(&dev->mutex);
      429 +                return (DDI_INTR_UNCLAIMED);
      430 +        }
      431 +
      432 +        /* Three interrupts, DAC1, DAC2, and ADC.  The UART we just toss. */
      433 +
      434 +        if (status & CONC_STATUS_DAC1INT) {
      435 +                port = &dev->port[PORT_DAC];
      436 +
      437 +                /* current frame counter is in high nybble */
      438 +                frameno = audioens_readmem(dev,
      439 +                    CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF) >> 16;
      440 +                n = frameno >= port->frameno ?
      441 +                    frameno - port->frameno :
      442 +                    frameno + port->nframes - port->frameno;
      443 +                port->frameno = frameno;
      444 +                port->count += n;
      445 +                CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
      446 +                SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
      447 +        }
      448 +        if (status & CONC_STATUS_ADCINT) {
      449 +                port = &dev->port[PORT_ADC];
      450 +
      451 +                /* current frame counter is in high nybble */
      452 +                frameno = audioens_readmem(dev,
      453 +                    CONC_ADCCTL_PAGE, CONC_wADCFC_OFF) >> 16;
      454 +                n = frameno >= port->frameno ?
      455 +                    frameno - port->frameno :
      456 +                    frameno + port->nframes - port->frameno;
      457 +                port->frameno = frameno;
      458 +                port->count += n;
      459 +                CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
      460 +                SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
      461 +        }
      462 +        if (status & CONC_STATUS_DAC2INT) {
      463 +                CLR8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC2IE);
      464 +                SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC2IE);
      465 +        }
      466 +        if (status & CONC_STATUS_UARTINT) {
      467 +                /*
      468 +                 * Consume data in the UART RX FIFO.  We don't support
      469 +                 * the UART for now, so just eat it.
      470 +                 */
      471 +                while (GET8(dev, CONC_bUARTCSTAT_OFF) & CONC_UART_RXRDY)
      472 +                        continue;
      473 +        }
      474 +        mutex_exit(&dev->mutex);
      475 +
      476 +        return (DDI_INTR_CLAIMED);
      477 +}
      478 +
      479 +static int
      480 +audioens_setup_intr(audioens_dev_t *dev)
      481 +{
      482 +        int     act;
      483 +        uint_t  ipri;
      484 +
      485 +        if ((ddi_intr_alloc(dev->dip, &dev->intrh, DDI_INTR_TYPE_FIXED, 0, 1,
      486 +            &act, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) || (act != 1)) {
      487 +                audio_dev_warn(dev->osdev, "can't alloc intr handle");
      488 +                goto fail;
      489 +        }
      490 +
      491 +        if (ddi_intr_get_pri(dev->intrh, &ipri) != DDI_SUCCESS) {
      492 +                audio_dev_warn(dev->osdev, "can't get interrupt priority");
      493 +                goto fail;
      494 +        }
      495 +        if (ddi_intr_add_handler(dev->intrh, audioens_intr, dev, NULL) !=
      496 +            DDI_SUCCESS) {
      497 +                audio_dev_warn(dev->osdev, "cannot add interrupt handler");
      498 +                goto fail;
      499 +        }
      500 +        dev->intrpri = ipri;
      501 +        return (DDI_SUCCESS);
      502 +
      503 +fail:
      504 +        if (dev->intrh != NULL) {
      505 +                (void) ddi_intr_free(dev->intrh);
      506 +                dev->intrh = NULL;
      507 +        }
      508 +        return (DDI_FAILURE);
      509 +}
      510 +
      511 +#endif  /* __x86 */
      512 +
 392  513  /*
 393  514   * Audio routines
 394  515   */
 395  516  static int
 396  517  audioens_format(void *arg)
 397  518  {
 398  519          _NOTE(ARGUNUSED(arg));
 399  520  
 400  521          /* hardware can also do AUDIO_FORMAT_U8, but no need for it */
 401  522          return (AUDIO_FORMAT_S16_LE);
↓ open down ↓ 18 lines elided ↑ open up ↑
 420  541  static int
 421  542  audioens_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
 422  543  {
 423  544          audioens_port_t *port = arg;
 424  545          audioens_dev_t  *dev = port->dev;
 425  546  
 426  547          _NOTE(ARGUNUSED(flag));
 427  548  
 428  549          mutex_enter(&dev->mutex);
 429  550  
 430      -        port->nframes = AUDIOENS_BUF_LEN / (port->nchan * sizeof (int16_t));
 431  551          port->count = 0;
 432  552  
 433  553          *nframes = port->nframes;
 434  554          *bufp = port->kaddr;
 435  555          mutex_exit(&dev->mutex);
 436  556  
 437  557          return (0);
 438  558  }
 439  559  
 440  560  static int
↓ open down ↓ 28 lines elided ↑ open up ↑
 469  589                  SET8(dev, CONC_bSERFMT_OFF,
 470  590                      CONC_PCM_DAC1_16BIT | CONC_PCM_DAC2_16BIT |
 471  591                      CONC_PCM_DAC1_STEREO | CONC_PCM_DAC2_STEREO);
 472  592  
 473  593                  /* Set the frame count */
 474  594                  audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF,
 475  595                      port->nframes - 1);
 476  596                  audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_wDAC2FC_OFF,
 477  597                      port->nframes - 1);
 478  598  
 479      -                /* Set # of frames between interrupts */
 480      -                PUT16(dev, CONC_wDAC1IC_OFF, port->nframes - 1);
 481      -                PUT16(dev, CONC_wDAC2IC_OFF, port->nframes - 1);
 482      -
      599 +                PUT16(dev, CONC_wDAC1IC_OFF, port->iframes - 1);
      600 +                PUT16(dev, CONC_wDAC2IC_OFF, port->iframes - 1);
 483  601                  SET8(dev, CONC_bDEVCTL_OFF,
 484  602                      CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);
      603 +#ifdef __x86
      604 +                if (dev->useintr) {
      605 +                        SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_DAC1IE);
      606 +                }
      607 +#endif
 485  608  
 486  609                  break;
 487  610  
 488  611          case PORT_ADC:
 489  612                  /* Set physical address of the DMA buffer */
 490  613                  audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
 491  614                      port->paddr);
 492  615  
 493  616                  /* Set ADC rate */
 494  617                  SRCSetRate(dev, SRC_ADC_BASE, port->speed);
↓ open down ↓ 5 lines elided ↑ open up ↑
 500  623  
 501  624                  PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 502  625  
 503  626                  PUT8(dev, CONC_bSERFMT_OFF, tmp);
 504  627  
 505  628                  /* Set the frame count */
 506  629                  audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
 507  630                      port->nframes - 1);
 508  631  
 509  632                  /* Set # of frames between interrupts */
 510      -                PUT16(dev, CONC_wADCIC_OFF, port->nframes - 1);
      633 +                PUT16(dev, CONC_wADCIC_OFF, port->iframes - 1);
 511  634  
 512  635                  SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
      636 +#ifdef __x86
      637 +                if (dev->useintr) {
      638 +                        SET8(dev, CONC_bSERCTL_OFF, CONC_SERCTL_ADCIE);
      639 +                }
      640 +#endif
 513  641                  break;
 514  642          }
 515  643  
 516  644          port->frameno = 0;
 517  645          mutex_exit(&dev->mutex);
 518  646  
 519  647          return (0);
 520  648  }
 521  649  
 522  650  static void
↓ open down ↓ 30 lines elided ↑ open up ↑
 553  681                  offs = CONC_wDAC1FC_OFF;
 554  682                  break;
 555  683  
 556  684          case PORT_ADC:
 557  685                  page = CONC_ADCCTL_PAGE;
 558  686                  offs = CONC_wADCFC_OFF;
 559  687                  break;
 560  688          }
 561  689  
 562  690          mutex_enter(&dev->mutex);
      691 +#ifdef __x86
      692 +        if (!dev->useintr) {
      693 +#endif
      694 +
 563  695          /*
 564  696           * Note that the current frame counter is in the high nybble.
 565  697           */
 566  698          frameno = audioens_readmem(port->dev, page, offs) >> 16;
 567  699          n = frameno >= port->frameno ?
 568  700              frameno - port->frameno :
 569  701              frameno + port->nframes - port->frameno;
 570  702          port->frameno = frameno;
 571  703          port->count += n;
 572  704  
      705 +#ifdef __x86
      706 +        }
      707 +#endif
      708 +
 573  709          val = port->count;
 574  710          mutex_exit(&dev->mutex);
 575  711  
 576  712          return (val);
 577  713  }
 578  714  
 579  715  static void
 580  716  audioens_close(void *arg)
 581  717  {
 582  718          _NOTE(ARGUNUSED(arg));
↓ open down ↓ 125 lines elided ↑ open up ↑
 708  844                  return (DDI_FAILURE);
 709  845          }
 710  846  
 711  847          for (int i = 0; i <= PORT_MAX; i++) {
 712  848                  audioens_port_t *port;
 713  849                  unsigned caps;
 714  850                  unsigned dmaflags;
 715  851                  size_t rlen;
 716  852                  ddi_dma_cookie_t c;
 717  853                  unsigned ccnt;
      854 +                size_t bufsz;
 718  855  
 719  856                  port = &dev->port[i];
 720  857                  port->dev = dev;
 721  858  
      859 +                /*
      860 +                 * We have 48000Hz.  At that rate, 128 frames will give
      861 +                 * us an interrupt rate of 375Hz.  2048 frames buys about
      862 +                 * 42ms of buffer.  Note that interrupts are only enabled
      863 +                 * for platforms which need them (i.e. VMWare).
      864 +                 */
      865 +
 722  866                  switch (i) {
 723  867                  case PORT_DAC:
 724  868                          port->nchan = 4;
 725  869                          port->speed = 48000;
      870 +                        port->iframes = 128;
      871 +                        port->nframes = 2048;
 726  872                          caps = ENGINE_OUTPUT_CAP;
 727  873                          dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
 728  874                          break;
 729  875  
 730  876                  case PORT_ADC:
 731  877                          port->nchan = 2;
 732  878                          port->speed = 48000;
      879 +                        port->iframes = 128;
      880 +                        port->nframes = 2048;
 733  881                          caps = ENGINE_INPUT_CAP;
 734  882                          dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
 735  883                          break;
 736  884                  }
 737  885  
 738  886                  port->num = i;
      887 +                bufsz = port->nframes * port->nchan * sizeof (uint16_t);
 739  888  
 740  889                  /*
 741  890                   * Allocate DMA resources.
 742  891                   */
 743  892  
 744  893                  if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
 745  894                      NULL, &port->dmah) != DDI_SUCCESS) {
 746  895                          audio_dev_warn(dev->osdev,
 747  896                              "port %d: dma handle allocation failed", i);
 748  897                          return (DDI_FAILURE);
 749  898                  }
 750      -                if (ddi_dma_mem_alloc(port->dmah, AUDIOENS_BUF_LEN, &buf_attr,
      899 +                if (ddi_dma_mem_alloc(port->dmah, bufsz, &buf_attr,
 751  900                      DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
 752  901                      &rlen, &port->acch) != DDI_SUCCESS) {
 753  902                          audio_dev_warn(dev->osdev,
 754  903                              "port %d: dma memory allocation failed", i);
 755  904                          return (DDI_FAILURE);
 756  905                  }
 757  906                  /* ensure that the buffer is zeroed out properly */
 758  907                  bzero(port->kaddr, rlen);
 759  908                  if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
 760      -                    AUDIOENS_BUF_LEN, dmaflags, DDI_DMA_SLEEP, NULL,
      909 +                    bufsz, dmaflags, DDI_DMA_SLEEP, NULL,
 761  910                      &c, &ccnt) != DDI_DMA_MAPPED) {
 762  911                          audio_dev_warn(dev->osdev,
 763  912                              "port %d: dma binding failed", i);
 764  913                          return (DDI_FAILURE);
 765  914                  }
 766  915                  port->paddr = c.dmac_address;
 767  916  
 768  917                  /*
 769  918                   * Allocate and configure audio engine.
 770  919                   */
↓ open down ↓ 1 lines elided ↑ open up ↑
 772  921                  if (port->engine == NULL) {
 773  922                          audio_dev_warn(dev->osdev,
 774  923                              "port %d: audio_engine_alloc failed", i);
 775  924                          return (DDI_FAILURE);
 776  925                  }
 777  926  
 778  927                  audio_engine_set_private(port->engine, port);
 779  928                  audio_dev_add_engine(dev->osdev, port->engine);
 780  929          }
 781  930  
 782      -        /*
 783      -         * Set up kstats for interrupt reporting.
 784      -         */
 785  931          if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
 786  932                  audio_dev_warn(dev->osdev,
 787  933                      "unable to register with audio framework");
 788  934                  return (DDI_FAILURE);
 789  935          }
 790  936  
 791  937          return (DDI_SUCCESS);
 792  938  }
 793  939  
 794  940  void
 795  941  audioens_destroy(audioens_dev_t *dev)
 796  942  {
 797  943          int     i;
 798  944  
      945 +#ifdef __x86
      946 +        if (dev->useintr && dev->intrh != NULL) {
      947 +                (void) ddi_intr_disable(dev->intrh);
      948 +                (void) ddi_intr_remove_handler(dev->intrh);
      949 +                (void) ddi_intr_free(dev->intrh);
      950 +                dev->intrh = NULL;
      951 +        }
      952 +#endif
      953 +
 799  954          mutex_destroy(&dev->mutex);
 800  955  
 801  956          /* free up ports, including DMA resources for ports */
 802  957          for (i = 0; i <= PORT_MAX; i++) {
 803  958                  audioens_port_t *port = &dev->port[i];
 804  959  
 805  960                  if (port->paddr != 0)
 806  961                          (void) ddi_dma_unbind_handle(port->dmah);
 807  962                  if (port->acch != NULL)
 808  963                          ddi_dma_mem_free(&port->acch);
↓ open down ↓ 31 lines elided ↑ open up ↑
 840  995          const char *chip_name;
 841  996          const char *chip_vers;
 842  997  
 843  998          dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
 844  999          dev->dip = dip;
 845 1000          ddi_set_driver_private(dip, dev);
 846 1001          mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
 847 1002  
 848 1003          if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
 849 1004                  audio_dev_warn(dev->osdev, "pci_config_setup failed");
 850      -                mutex_destroy(&dev->mutex);
 851      -                kmem_free(dev, sizeof (*dev));
 852      -                return (DDI_FAILURE);
     1005 +                goto err_exit;
 853 1006          }
 854 1007  
 855 1008          vendor = pci_config_get16(pcih, PCI_CONF_VENID);
 856 1009          device = pci_config_get16(pcih, PCI_CONF_DEVID);
 857 1010          revision = pci_config_get8(pcih, PCI_CONF_REVID);
 858 1011  
 859 1012          if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
 860 1013              (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
 861 1014              device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
 862      -            device != ENSONIQ_ES5880B))
     1015 +            device != ENSONIQ_ES5880B)) {
     1016 +                audio_dev_warn(dev->osdev, "unrecognized device");
 863 1017                  goto err_exit;
     1018 +        }
 864 1019  
 865 1020          chip_name = "AudioPCI97";
 866 1021          chip_vers = "unknown";
 867 1022  
 868 1023          switch (device) {
 869 1024          case ENSONIQ_ES1371:
 870 1025                  chip_name = "AudioPCI97";
 871 1026                  switch (revision) {
 872 1027                  case 0x02:
 873 1028                  case 0x09:
↓ open down ↓ 52 lines elided ↑ open up ↑
 926 1081          pci_command |= PCI_COMM_ME | PCI_COMM_IO;
 927 1082          pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
 928 1083  
 929 1084          /* map registers */
 930 1085          if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
 931 1086              &dev->acch) != DDI_SUCCESS) {
 932 1087                  audio_dev_warn(dev->osdev, "can't map registers");
 933 1088                  goto err_exit;
 934 1089          }
 935 1090  
     1091 +#ifdef __x86
     1092 +        /*
     1093 +         * Virtual platforms (mostly VMWare!) seem to need us to pulse
     1094 +         * the interrupt enables to make progress.  So enable (emulated)
     1095 +         * hardware interrupts.
     1096 +         */
     1097 +        dev->useintr = B_FALSE;
     1098 +        if (get_hwenv() & HW_VIRTUAL) {
     1099 +                dev->useintr = B_TRUE;
     1100 +                if (audioens_setup_intr(dev) != DDI_SUCCESS) {
     1101 +                        goto err_exit;
     1102 +                }
     1103 +                /* Reinitialize the mutex with interrupt priority. */
     1104 +                mutex_destroy(&dev->mutex);
     1105 +                mutex_init(&dev->mutex, NULL, MUTEX_DRIVER,
     1106 +                    DDI_INTR_PRI(dev->intrpri));
     1107 +        }
     1108 +#endif
     1109 +
 936 1110          /* This allocates and configures the engines */
 937 1111          if (audioens_init(dev) != DDI_SUCCESS) {
 938 1112                  audio_dev_warn(dev->osdev, "can't init device");
 939 1113                  goto err_exit;
 940 1114          }
 941 1115  
     1116 +#ifdef __x86
     1117 +        if (dev->useintr) {
     1118 +                (void) ddi_intr_enable(dev->intrh);
     1119 +        }
     1120 +#endif
 942 1121          pci_config_teardown(&pcih);
 943 1122  
 944 1123          ddi_report_dev(dip);
 945 1124  
 946 1125          return (DDI_SUCCESS);
 947 1126  
 948 1127  err_exit:
 949 1128          pci_config_teardown(&pcih);
 950 1129  
 951 1130          audioens_destroy(dev);
↓ open down ↓ 29 lines elided ↑ open up ↑
 981 1160          mutex_exit(&dev->mutex);
 982 1161  
 983 1162          audioens_destroy(dev);
 984 1163  
 985 1164          return (DDI_SUCCESS);
 986 1165  }
 987 1166  
 988 1167  static int
 989 1168  audioens_resume(audioens_dev_t *dev)
 990 1169  {
     1170 +        mutex_enter(&dev->mutex);
     1171 +        dev->suspended = B_FALSE;
     1172 +        mutex_exit(&dev->mutex);
     1173 +
 991 1174          /* reinitialize hardware */
 992 1175          audioens_init_hw(dev);
 993 1176  
 994 1177          /* restore AC97 state */
 995 1178          ac97_reset(dev->ac97);
 996 1179  
 997 1180          audio_dev_resume(dev->osdev);
 998 1181  
 999 1182          return (DDI_SUCCESS);
1000 1183  }
1001 1184  
1002 1185  static int
1003 1186  audioens_suspend(audioens_dev_t *dev)
1004 1187  {
1005 1188          audio_dev_suspend(dev->osdev);
1006 1189  
     1190 +        mutex_enter(&dev->mutex);
     1191 +        CLR8(dev, CONC_bDEVCTL_OFF,
     1192 +            CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN | CONC_DEVCTL_ADC_EN);
     1193 +        dev->suspended = B_TRUE;
     1194 +        mutex_exit(&dev->mutex);
     1195 +
1007 1196          return (DDI_SUCCESS);
1008 1197  }
1009 1198  
1010 1199  static int
1011 1200  audioens_quiesce(dev_info_t *dip)
1012 1201  {
1013 1202          audioens_dev_t  *dev;
1014 1203          uint8_t         tmp;
1015 1204  
1016 1205          if ((dev = ddi_get_driver_private(dip)) == NULL) {
↓ open down ↓ 119 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX