1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2016 Garrett D'Amore <garrett@damore.org>
  24  */
  25 /*
  26  * Purpose: Creative/Ensoniq AudioPCI97  driver (ES1371/ES1373)
  27  *
  28  * This driver is used with the original Ensoniq AudioPCI97 card and many
  29  * PCI based Sound Blaster cards by Creative Technologies. For example
  30  * Sound Blaster PCI128 and Creative/Ectiva EV1938.
  31  */
  32 
  33 /*
  34  * This file is part of Open Sound System
  35  *
  36  * Copyright (C) 4Front Technologies 1996-2008.
  37  *
  38  * This software is released under CDDL 1.0 source license.
  39  * See the COPYING file included in the main directory of this source
  40  * distribution for the license terms and conditions.
  41  */
  42 
  43 #include <sys/audio/audio_driver.h>
  44 #include <sys/audio/ac97.h>
  45 #include <sys/note.h>
  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 
  59 #include "audioens.h"
  60 
  61 /*
  62  * Set the latency to 32, 64, 96, 128 clocks - some APCI97 devices exhibit
  63  * garbled audio in some cases and setting the latency to higer values fixes it
  64  * Values: 32, 64, 96, 128 - Default: 64 (or defined by bios)
  65  */
  66 int audioens_latency = 0;
  67 
  68 /*
  69  * Enable SPDIF port on SoundBlaster 128D or Sound Blaster Digital-4.1 models
  70  * Values: 1=Enable 0=Disable Default: 0
  71  */
  72 int audioens_spdif = 0;
  73 
  74 /*
  75  * Note: Latest devices can support SPDIF with AC3 pass thru.
  76  * However, in order to do this, one of the two DMA engines must be
  77  * dedicated to this, which would prevent the card from supporting 4
  78  * channel audio.  For now we don't bother with the AC3 pass through
  79  * mode, and instead just focus on 4 channel support.  In the future,
  80  * this could be selectable via a property.
  81  */
  82 
  83 #define ENSONIQ_VENDOR_ID       0x1274
  84 #define CREATIVE_VENDOR_ID      0x1102
  85 #define ECTIVA_VENDOR_ID        0x1102
  86 #define ENSONIQ_ES1371          0x1371
  87 #define ENSONIQ_ES5880          0x8001
  88 #define ENSONIQ_ES5880A         0x8002
  89 #define ENSONIQ_ES5880B         0x5880
  90 #define ECTIVA_ES1938           0x8938
  91 
  92 #define DEFRATE                 48000
  93 #define DRVNAME                 "audioens"
  94 
  95 typedef struct audioens_port
  96 {
  97         /* Audio parameters */
  98         int                     speed;
  99 
 100         int                     num;
 101 #define PORT_DAC                0
 102 #define PORT_ADC                1
 103 #define PORT_MAX                PORT_ADC
 104 
 105         caddr_t                 kaddr;
 106         uint32_t                paddr;
 107         ddi_acc_handle_t        acch;
 108         ddi_dma_handle_t        dmah;
 109         int                     nchan;
 110         unsigned                nframes;
 111         unsigned                iframes;
 112         unsigned                frameno;
 113         uint64_t                count;
 114 
 115         struct audioens_dev     *dev;
 116         audio_engine_t          *engine;
 117 } audioens_port_t;
 118 
 119 typedef struct audioens_dev
 120 {
 121         audio_dev_t             *osdev;
 122         kmutex_t                mutex;
 123         uint16_t                devid;
 124         uint8_t                 revision;
 125         dev_info_t              *dip;
 126 
 127         audioens_port_t         port[PORT_MAX + 1];
 128 
 129         ac97_t                  *ac97;
 130 
 131         caddr_t                 regs;
 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
 141 } audioens_dev_t;
 142 
 143 static ddi_device_acc_attr_t acc_attr = {
 144         DDI_DEVICE_ATTR_V0,
 145         DDI_STRUCTURE_LE_ACC,
 146         DDI_STRICTORDER_ACC
 147 };
 148 
 149 static ddi_device_acc_attr_t buf_attr = {
 150         DDI_DEVICE_ATTR_V0,
 151         DDI_NEVERSWAP_ACC,
 152         DDI_STRICTORDER_ACC
 153 };
 154 
 155 static ddi_dma_attr_t dma_attr = {
 156         DMA_ATTR_VERSION,       /* dma_attr_version */
 157         0x0,                    /* dma_attr_addr_lo */
 158         0xffffffffU,            /* dma_attr_addr_hi */
 159         0x3ffff,                /* dma_attr_count_max */
 160         0x8,                    /* dma_attr_align */
 161         0x7f,                   /* dma_attr_burstsizes */
 162         0x1,                    /* dma_attr_minxfer */
 163         0x3ffff,                /* dma_attr_maxxfer */
 164         0x3ffff,                /* dma_attr_seg */
 165         0x1,                    /* dma_attr_sgllen */
 166         0x1,                    /* dma_attr_granular */
 167         0                       /* dma_attr_flags */
 168 };
 169 
 170 #define GET8(dev, offset)       \
 171         ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
 172 #define GET16(dev, offset)      \
 173         ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
 174 #define GET32(dev, offset)      \
 175         ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)))
 176 #define PUT8(dev, offset, v)    \
 177         ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v)
 178 #define PUT16(dev, offset, v)   \
 179         ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v)
 180 #define PUT32(dev, offset, v)   \
 181         ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v)
 182 
 183 #define CLR8(dev, offset, v)    PUT8(dev, offset, GET8(dev, offset) & ~(v))
 184 #define SET8(dev, offset, v)    PUT8(dev, offset, GET8(dev, offset) | (v))
 185 #define CLR32(dev, offset, v)   PUT32(dev, offset, GET32(dev, offset) & ~(v))
 186 #define SET32(dev, offset, v)   PUT32(dev, offset, GET32(dev, offset) | (v))
 187 
 188 static void audioens_init_hw(audioens_dev_t *);
 189 
 190 static uint16_t
 191 audioens_rd97(void *dev_, uint8_t wAddr)
 192 {
 193         audioens_dev_t *dev = dev_;
 194         int i, dtemp;
 195 
 196         mutex_enter(&dev->mutex);
 197         dtemp = GET32(dev, CONC_dCODECCTL_OFF);
 198         /* wait for WIP to go away saving the current state for later */
 199         for (i = 0; i < 0x100UL; ++i) {
 200                 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
 201                 if ((dtemp & (1UL << 30)) == 0)
 202                         break;
 203         }
 204 
 205         /* write addr w/data=0 and assert read request ... */
 206         PUT32(dev, CONC_dCODECCTL_OFF, ((int)wAddr << 16) | (1UL << 23));
 207 
 208         /* now wait for the data (RDY) */
 209         for (i = 0; i < 0x100UL; ++i) {
 210                 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
 211                 if (dtemp & (1UL << 31))
 212                         break;
 213         }
 214         dtemp = GET32(dev, CONC_dCODECCTL_OFF);
 215         mutex_exit(&dev->mutex);
 216 
 217         return (dtemp & 0xffff);
 218 }
 219 
 220 static void
 221 audioens_wr97(void *dev_, uint8_t wAddr, uint16_t wData)
 222 {
 223         audioens_dev_t *dev = dev_;
 224         int i, dtemp;
 225 
 226         mutex_enter(&dev->mutex);
 227         /* wait for WIP to go away */
 228         for (i = 0; i < 0x100UL; ++i) {
 229                 dtemp = GET32(dev, CONC_dCODECCTL_OFF);
 230                 if ((dtemp & (1UL << 30)) == 0)
 231                         break;
 232         }
 233 
 234         PUT32(dev, CONC_dCODECCTL_OFF, ((int)wAddr << 16) | wData);
 235 
 236         mutex_exit(&dev->mutex);
 237 }
 238 
 239 static unsigned short
 240 SRCRegRead(audioens_dev_t *dev, unsigned short reg)
 241 {
 242         int i, dtemp;
 243 
 244         dtemp = GET32(dev, CONC_dSRCIO_OFF);
 245         /* wait for ready */
 246         for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
 247                 dtemp = GET32(dev, CONC_dSRCIO_OFF);
 248                 if ((dtemp & SRC_BUSY) == 0)
 249                         break;
 250         }
 251 
 252         /* assert a read request */
 253         PUT32(dev, CONC_dSRCIO_OFF, (dtemp & SRC_CTLMASK) | ((int)reg << 25));
 254 
 255         /* now wait for the data */
 256         for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
 257                 dtemp = GET32(dev, CONC_dSRCIO_OFF);
 258                 if ((dtemp & SRC_BUSY) == 0)
 259                         break;
 260         }
 261 
 262         return ((unsigned short) dtemp);
 263 }
 264 
 265 static void
 266 SRCRegWrite(audioens_dev_t *dev, unsigned short reg, unsigned short val)
 267 {
 268         int i, dtemp;
 269         int writeval;
 270 
 271         dtemp = GET32(dev, CONC_dSRCIO_OFF);
 272         /* wait for ready */
 273         for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
 274                 dtemp = GET32(dev, CONC_dSRCIO_OFF);
 275                 if ((dtemp & SRC_BUSY) == 0)
 276                         break;
 277         }
 278 
 279         /* assert the write request */
 280         writeval = (dtemp & SRC_CTLMASK) | SRC_WENABLE |
 281             ((int)reg << 25) | val;
 282         PUT32(dev, CONC_dSRCIO_OFF, writeval);
 283 }
 284 
 285 static void
 286 SRCSetRate(audioens_dev_t *dev, unsigned char base, unsigned short rate)
 287 {
 288         int i, freq, dtemp;
 289         unsigned short N, truncM, truncStart;
 290 
 291         if (base != SRC_ADC_BASE) {
 292                 /* freeze the channel */
 293                 dtemp = (base == SRC_DAC1_BASE) ?
 294                     SRC_DAC1FREEZE : SRC_DAC2FREEZE;
 295                 for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
 296                         if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
 297                                 break;
 298                 }
 299                 PUT32(dev, CONC_dSRCIO_OFF,
 300                     (GET32(dev, CONC_dSRCIO_OFF) & SRC_CTLMASK) | dtemp);
 301 
 302                 /* calculate new frequency and write it - preserve accum */
 303                 freq = ((int)rate << 16) / 3000U;
 304                 SRCRegWrite(dev, (unsigned short) base + SRC_INT_REGS_OFF,
 305                     (SRCRegRead(dev, (unsigned short) base + SRC_INT_REGS_OFF)
 306                     & 0x00ffU) | ((unsigned short) (freq >> 6) & 0xfc00));
 307                 SRCRegWrite(dev, (unsigned short) base + SRC_VFREQ_FRAC_OFF,
 308                     (unsigned short) freq >> 1);
 309 
 310                 /* un-freeze the channel */
 311                 for (i = 0; i < SRC_IOPOLL_COUNT; ++i)
 312                         if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
 313                                 break;
 314                 PUT32(dev, CONC_dSRCIO_OFF,
 315                     (GET32(dev, CONC_dSRCIO_OFF) & SRC_CTLMASK) & ~dtemp);
 316         } else {
 317                 /* derive oversample ratio */
 318                 N = rate / 3000U;
 319                 if (N == 15 || N == 13 || N == 11 || N == 9)
 320                         --N;
 321 
 322                 /* truncate the filter and write n/trunc_start */
 323                 truncM = (21 * N - 1) | 1;
 324                 if (rate >= 24000U) {
 325                         if (truncM > 239)
 326                                 truncM = 239;
 327                         truncStart = (239 - truncM) >> 1;
 328 
 329                         SRCRegWrite(dev, base + SRC_TRUNC_N_OFF,
 330                             (truncStart << 9) | (N << 4));
 331                 } else {
 332                         if (truncM > 119)
 333                                 truncM = 119;
 334                         truncStart = (119 - truncM) >> 1;
 335 
 336                         SRCRegWrite(dev, base + SRC_TRUNC_N_OFF,
 337                             0x8000U | (truncStart << 9) | (N << 4));
 338                 }
 339 
 340                 /* calculate new frequency and write it - preserve accum */
 341                 freq = ((48000UL << 16) / rate) * N;
 342                 SRCRegWrite(dev, base + SRC_INT_REGS_OFF,
 343                     (SRCRegRead(dev, (unsigned short) base + SRC_INT_REGS_OFF)
 344                     & 0x00ff) | ((unsigned short) (freq >> 6) & 0xfc00));
 345                 SRCRegWrite(dev, base + SRC_VFREQ_FRAC_OFF,
 346                     (unsigned short) freq >> 1);
 347 
 348                 SRCRegWrite(dev, SRC_ADC_VOL_L, N << 8);
 349                 SRCRegWrite(dev, SRC_ADC_VOL_R, N << 8);
 350         }
 351 }
 352 
 353 static void
 354 SRCInit(audioens_dev_t *dev)
 355 {
 356         int i;
 357 
 358         /* Clear all SRC RAM then init - keep SRC disabled until done */
 359         for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
 360                 if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
 361                         break;
 362         }
 363         PUT32(dev, CONC_dSRCIO_OFF, SRC_DISABLE);
 364 
 365         for (i = 0; i < 0x80; ++i)
 366                 SRCRegWrite(dev, (unsigned short) i, 0U);
 367 
 368         SRCRegWrite(dev, SRC_DAC1_BASE + SRC_TRUNC_N_OFF, 16 << 4);
 369         SRCRegWrite(dev, SRC_DAC1_BASE + SRC_INT_REGS_OFF, 16 << 10);
 370         SRCRegWrite(dev, SRC_DAC2_BASE + SRC_TRUNC_N_OFF, 16 << 4);
 371         SRCRegWrite(dev, SRC_DAC2_BASE + SRC_INT_REGS_OFF, 16 << 10);
 372         SRCRegWrite(dev, SRC_DAC1_VOL_L, 1 << 12);
 373         SRCRegWrite(dev, SRC_DAC1_VOL_R, 1 << 12);
 374         SRCRegWrite(dev, SRC_DAC2_VOL_L, 1 << 12);
 375         SRCRegWrite(dev, SRC_DAC2_VOL_R, 1 << 12);
 376         SRCRegWrite(dev, SRC_ADC_VOL_L, 1 << 12);
 377         SRCRegWrite(dev, SRC_ADC_VOL_R, 1 << 12);
 378 
 379         /* default some rates */
 380         SRCSetRate(dev, SRC_DAC1_BASE, 48000);
 381         SRCSetRate(dev, SRC_DAC2_BASE, 48000);
 382         SRCSetRate(dev, SRC_ADC_BASE, 48000);
 383 
 384         /* now enable the whole deal */
 385         for (i = 0; i < SRC_IOPOLL_COUNT; ++i) {
 386                 if (!(GET32(dev, CONC_dSRCIO_OFF) & SRC_BUSY))
 387                         break;
 388         }
 389         PUT32(dev, CONC_dSRCIO_OFF, 0);
 390 }
 391 
 392 static void
 393 audioens_writemem(audioens_dev_t *dev, uint32_t page, uint32_t offs,
 394     uint32_t data)
 395 {
 396         /* Select memory page */
 397         PUT32(dev, CONC_bMEMPAGE_OFF, page);
 398         PUT32(dev, offs, data);
 399 }
 400 
 401 static uint32_t
 402 audioens_readmem(audioens_dev_t *dev, uint32_t page, uint32_t offs)
 403 {
 404         PUT32(dev, CONC_bMEMPAGE_OFF, page);    /* Select memory page */
 405         return (GET32(dev, offs));
 406 }
 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 
 513 /*
 514  * Audio routines
 515  */
 516 static int
 517 audioens_format(void *arg)
 518 {
 519         _NOTE(ARGUNUSED(arg));
 520 
 521         /* hardware can also do AUDIO_FORMAT_U8, but no need for it */
 522         return (AUDIO_FORMAT_S16_LE);
 523 }
 524 
 525 static int
 526 audioens_channels(void *arg)
 527 {
 528         audioens_port_t *port = arg;
 529 
 530         return (port->nchan);
 531 }
 532 
 533 static int
 534 audioens_rate(void *arg)
 535 {
 536         audioens_port_t *port = arg;
 537 
 538         return (port->speed);
 539 }
 540 
 541 static int
 542 audioens_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
 543 {
 544         audioens_port_t *port = arg;
 545         audioens_dev_t  *dev = port->dev;
 546 
 547         _NOTE(ARGUNUSED(flag));
 548 
 549         mutex_enter(&dev->mutex);
 550 
 551         port->count = 0;
 552 
 553         *nframes = port->nframes;
 554         *bufp = port->kaddr;
 555         mutex_exit(&dev->mutex);
 556 
 557         return (0);
 558 }
 559 
 560 static int
 561 audioens_start(void *arg)
 562 {
 563         audioens_port_t *port = arg;
 564         audioens_dev_t *dev = port->dev;
 565         uint32_t tmp;
 566 
 567         mutex_enter(&dev->mutex);
 568 
 569         switch (port->num) {
 570         case PORT_DAC:
 571                 /* Set physical address of the DMA buffer */
 572                 audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_dDAC1PADDR_OFF,
 573                     port->paddr);
 574                 audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_dDAC2PADDR_OFF,
 575                     port->paddr + (port->nframes * sizeof (int16_t) * 2));
 576 
 577                 /* Set DAC rate */
 578                 SRCSetRate(dev, SRC_DAC1_BASE, port->speed);
 579                 SRCSetRate(dev, SRC_DAC2_BASE, port->speed);
 580 
 581                 /* Configure the channel setup - SPDIF only uses front */
 582                 tmp = GET32(dev, CONC_dSTATUS_OFF);
 583                 tmp &= ~(CONC_STATUS_SPKR_MASK | CONC_STATUS_SPDIF_MASK);
 584                 tmp |= CONC_STATUS_SPKR_4CH | CONC_STATUS_SPDIF_P1;
 585                 PUT32(dev, CONC_dSTATUS_OFF, tmp);
 586 
 587                 /* Set format */
 588                 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 589                 SET8(dev, CONC_bSERFMT_OFF,
 590                     CONC_PCM_DAC1_16BIT | CONC_PCM_DAC2_16BIT |
 591                     CONC_PCM_DAC1_STEREO | CONC_PCM_DAC2_STEREO);
 592 
 593                 /* Set the frame count */
 594                 audioens_writemem(dev, CONC_DAC1CTL_PAGE, CONC_wDAC1FC_OFF,
 595                     port->nframes - 1);
 596                 audioens_writemem(dev, CONC_DAC2CTL_PAGE, CONC_wDAC2FC_OFF,
 597                     port->nframes - 1);
 598 
 599                 PUT16(dev, CONC_wDAC1IC_OFF, port->iframes - 1);
 600                 PUT16(dev, CONC_wDAC2IC_OFF, port->iframes - 1);
 601                 SET8(dev, CONC_bDEVCTL_OFF,
 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
 608 
 609                 break;
 610 
 611         case PORT_ADC:
 612                 /* Set physical address of the DMA buffer */
 613                 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
 614                     port->paddr);
 615 
 616                 /* Set ADC rate */
 617                 SRCSetRate(dev, SRC_ADC_BASE, port->speed);
 618 
 619                 /* Set format - for input we only support 16 bit input */
 620                 tmp = GET8(dev, CONC_bSERFMT_OFF);
 621                 tmp |= CONC_PCM_ADC_16BIT;
 622                 tmp |= CONC_PCM_ADC_STEREO;
 623 
 624                 PUT8(dev, CONC_bSKIPC_OFF, 0x10);
 625 
 626                 PUT8(dev, CONC_bSERFMT_OFF, tmp);
 627 
 628                 /* Set the frame count */
 629                 audioens_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
 630                     port->nframes - 1);
 631 
 632                 /* Set # of frames between interrupts */
 633                 PUT16(dev, CONC_wADCIC_OFF, port->iframes - 1);
 634 
 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
 641                 break;
 642         }
 643 
 644         port->frameno = 0;
 645         mutex_exit(&dev->mutex);
 646 
 647         return (0);
 648 }
 649 
 650 static void
 651 audioens_stop(void *arg)
 652 {
 653         audioens_port_t *port = arg;
 654         audioens_dev_t *dev = port->dev;
 655 
 656         mutex_enter(&dev->mutex);
 657         switch (port->num) {
 658         case PORT_DAC:
 659                 CLR8(dev, CONC_bDEVCTL_OFF,
 660                     CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN);
 661                 break;
 662         case PORT_ADC:
 663                 CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
 664                 break;
 665         }
 666         mutex_exit(&dev->mutex);
 667 }
 668 
 669 static uint64_t
 670 audioens_count(void *arg)
 671 {
 672         audioens_port_t *port = arg;
 673         audioens_dev_t *dev = port->dev;
 674         uint64_t val;
 675         uint32_t page, offs;
 676         int frameno, n;
 677 
 678         switch (port->num) {
 679         case PORT_DAC:
 680                 page = CONC_DAC1CTL_PAGE;
 681                 offs = CONC_wDAC1FC_OFF;
 682                 break;
 683 
 684         case PORT_ADC:
 685                 page = CONC_ADCCTL_PAGE;
 686                 offs = CONC_wADCFC_OFF;
 687                 break;
 688         }
 689 
 690         mutex_enter(&dev->mutex);
 691 #ifdef __x86
 692         if (!dev->useintr) {
 693 #endif
 694 
 695         /*
 696          * Note that the current frame counter is in the high nybble.
 697          */
 698         frameno = audioens_readmem(port->dev, page, offs) >> 16;
 699         n = frameno >= port->frameno ?
 700             frameno - port->frameno :
 701             frameno + port->nframes - port->frameno;
 702         port->frameno = frameno;
 703         port->count += n;
 704 
 705 #ifdef __x86
 706         }
 707 #endif
 708 
 709         val = port->count;
 710         mutex_exit(&dev->mutex);
 711 
 712         return (val);
 713 }
 714 
 715 static void
 716 audioens_close(void *arg)
 717 {
 718         _NOTE(ARGUNUSED(arg));
 719 }
 720 
 721 static void
 722 audioens_sync(void *arg, unsigned nframes)
 723 {
 724         audioens_port_t *port = arg;
 725 
 726         _NOTE(ARGUNUSED(nframes));
 727 
 728         if (port->num == PORT_ADC) {
 729                 (void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
 730         } else {
 731                 (void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
 732         }
 733 }
 734 
 735 static void
 736 audioens_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
 737 {
 738         audioens_port_t *port = arg;
 739 
 740         if ((port->num == PORT_DAC) && (chan >= 2)) {
 741                 *offset = (port->nframes * 2) + (chan % 2);
 742                 *incr = 2;
 743         } else {
 744                 *offset = chan;
 745                 *incr = 2;
 746         }
 747 }
 748 
 749 audio_engine_ops_t audioens_engine_ops = {
 750         AUDIO_ENGINE_VERSION,           /* version number */
 751         audioens_open,
 752         audioens_close,
 753         audioens_start,
 754         audioens_stop,
 755         audioens_count,
 756         audioens_format,
 757         audioens_channels,
 758         audioens_rate,
 759         audioens_sync,
 760         NULL,
 761         audioens_chinfo,
 762         NULL,
 763 };
 764 
 765 void
 766 audioens_init_hw(audioens_dev_t *dev)
 767 {
 768         int tmp;
 769 
 770         if ((dev->devid == ENSONIQ_ES5880) ||
 771             (dev->devid == ENSONIQ_ES5880A) ||
 772             (dev->devid == ENSONIQ_ES5880B) ||
 773             (dev->devid == 0x1371 && dev->revision == 7) ||
 774             (dev->devid == 0x1371 && dev->revision >= 9)) {
 775 
 776                 /* Have a ES5880 so enable the codec manually */
 777                 tmp = GET8(dev, CONC_bINTSUMM_OFF) & 0xff;
 778                 tmp |= 0x20;
 779                 PUT8(dev, CONC_bINTSUMM_OFF, tmp);
 780                 for (int i = 0; i < 2000; i++)
 781                         drv_usecwait(10);
 782         }
 783 
 784         SRCInit(dev);
 785 
 786         /*
 787          * Turn on CODEC (UART and joystick left disabled)
 788          */
 789         tmp = GET32(dev, CONC_bDEVCTL_OFF) & 0xff;
 790         tmp &= ~(CONC_DEVCTL_PCICLK_DS | CONC_DEVCTL_XTALCLK_DS);
 791         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
 792         PUT8(dev, CONC_bUARTCSTAT_OFF, 0x00);
 793 
 794         /* Perform AC97 codec warm reset */
 795         tmp = GET8(dev, CONC_bMISCCTL_OFF) & 0xff;
 796         PUT8(dev, CONC_bMISCCTL_OFF, tmp | CONC_MISCCTL_SYNC_RES);
 797         drv_usecwait(200);
 798         PUT8(dev, CONC_bMISCCTL_OFF, tmp);
 799         drv_usecwait(200);
 800 
 801         if (dev->revision >= 4) {
 802                 /* XXX: enable SPDIF - PCM only for now */
 803                 if (audioens_spdif) {
 804                         /* enable SPDIF */
 805                         PUT32(dev, 0x04, GET32(dev, 0x04) | (1 << 18));
 806                         /* SPDIF out = data from DAC */
 807                         PUT32(dev, 0x00, GET32(dev, 0x00) | (1 << 26));
 808                         CLR32(dev, CONC_dSPDIF_OFF, CONC_SPDIF_AC3);
 809 
 810                 } else {
 811                         /* disable spdif out */
 812                         PUT32(dev, 0x04, GET32(dev, 0x04) & ~(1 << 18));
 813                         PUT32(dev, 0x00, GET32(dev, 0x00) & ~(1 << 26));
 814                 }
 815 
 816                 /* we want to run each channel independently */
 817                 CLR32(dev, CONC_dSTATUS_OFF, CONC_STATUS_ECHO);
 818         }
 819 }
 820 
 821 static int
 822 audioens_init(audioens_dev_t *dev)
 823 {
 824 
 825         audioens_init_hw(dev);
 826 
 827         /*
 828          * On this hardware, we want to disable the internal speaker by
 829          * default, if it exists.  (We don't have a speakerphone on any
 830          * of these cards, and no SPARC hardware uses it either!)
 831          */
 832         (void) ddi_prop_update_int(DDI_DEV_T_NONE, dev->dip, AC97_PROP_SPEAKER,
 833             0);
 834 
 835         /*
 836          * Init mixer
 837          */
 838 
 839         dev->ac97 = ac97_alloc(dev->dip, audioens_rd97, audioens_wr97, dev);
 840         if (dev->ac97 == NULL)
 841                 return (DDI_FAILURE);
 842 
 843         if (ac97_init(dev->ac97, dev->osdev) != 0) {
 844                 return (DDI_FAILURE);
 845         }
 846 
 847         for (int i = 0; i <= PORT_MAX; i++) {
 848                 audioens_port_t *port;
 849                 unsigned caps;
 850                 unsigned dmaflags;
 851                 size_t rlen;
 852                 ddi_dma_cookie_t c;
 853                 unsigned ccnt;
 854                 size_t bufsz;
 855 
 856                 port = &dev->port[i];
 857                 port->dev = dev;
 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 
 866                 switch (i) {
 867                 case PORT_DAC:
 868                         port->nchan = 4;
 869                         port->speed = 48000;
 870                         port->iframes = 128;
 871                         port->nframes = 2048;
 872                         caps = ENGINE_OUTPUT_CAP;
 873                         dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
 874                         break;
 875 
 876                 case PORT_ADC:
 877                         port->nchan = 2;
 878                         port->speed = 48000;
 879                         port->iframes = 128;
 880                         port->nframes = 2048;
 881                         caps = ENGINE_INPUT_CAP;
 882                         dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
 883                         break;
 884                 }
 885 
 886                 port->num = i;
 887                 bufsz = port->nframes * port->nchan * sizeof (uint16_t);
 888 
 889                 /*
 890                  * Allocate DMA resources.
 891                  */
 892 
 893                 if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
 894                     NULL, &port->dmah) != DDI_SUCCESS) {
 895                         audio_dev_warn(dev->osdev,
 896                             "port %d: dma handle allocation failed", i);
 897                         return (DDI_FAILURE);
 898                 }
 899                 if (ddi_dma_mem_alloc(port->dmah, bufsz, &buf_attr,
 900                     DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
 901                     &rlen, &port->acch) != DDI_SUCCESS) {
 902                         audio_dev_warn(dev->osdev,
 903                             "port %d: dma memory allocation failed", i);
 904                         return (DDI_FAILURE);
 905                 }
 906                 /* ensure that the buffer is zeroed out properly */
 907                 bzero(port->kaddr, rlen);
 908                 if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
 909                     bufsz, dmaflags, DDI_DMA_SLEEP, NULL,
 910                     &c, &ccnt) != DDI_DMA_MAPPED) {
 911                         audio_dev_warn(dev->osdev,
 912                             "port %d: dma binding failed", i);
 913                         return (DDI_FAILURE);
 914                 }
 915                 port->paddr = c.dmac_address;
 916 
 917                 /*
 918                  * Allocate and configure audio engine.
 919                  */
 920                 port->engine = audio_engine_alloc(&audioens_engine_ops, caps);
 921                 if (port->engine == NULL) {
 922                         audio_dev_warn(dev->osdev,
 923                             "port %d: audio_engine_alloc failed", i);
 924                         return (DDI_FAILURE);
 925                 }
 926 
 927                 audio_engine_set_private(port->engine, port);
 928                 audio_dev_add_engine(dev->osdev, port->engine);
 929         }
 930 
 931         if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
 932                 audio_dev_warn(dev->osdev,
 933                     "unable to register with audio framework");
 934                 return (DDI_FAILURE);
 935         }
 936 
 937         return (DDI_SUCCESS);
 938 }
 939 
 940 void
 941 audioens_destroy(audioens_dev_t *dev)
 942 {
 943         int     i;
 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 
 954         mutex_destroy(&dev->mutex);
 955 
 956         /* free up ports, including DMA resources for ports */
 957         for (i = 0; i <= PORT_MAX; i++) {
 958                 audioens_port_t *port = &dev->port[i];
 959 
 960                 if (port->paddr != 0)
 961                         (void) ddi_dma_unbind_handle(port->dmah);
 962                 if (port->acch != NULL)
 963                         ddi_dma_mem_free(&port->acch);
 964                 if (port->dmah != NULL)
 965                         ddi_dma_free_handle(&port->dmah);
 966 
 967                 if (port->engine != NULL) {
 968                         audio_dev_remove_engine(dev->osdev, port->engine);
 969                         audio_engine_free(port->engine);
 970                 }
 971         }
 972 
 973         if (dev->acch != NULL) {
 974                 ddi_regs_map_free(&dev->acch);
 975         }
 976 
 977         if (dev->ac97) {
 978                 ac97_free(dev->ac97);
 979         }
 980 
 981         if (dev->osdev != NULL) {
 982                 audio_dev_free(dev->osdev);
 983         }
 984 
 985         kmem_free(dev, sizeof (*dev));
 986 }
 987 
 988 int
 989 audioens_attach(dev_info_t *dip)
 990 {
 991         uint16_t pci_command, vendor, device;
 992         uint8_t revision;
 993         audioens_dev_t *dev;
 994         ddi_acc_handle_t pcih;
 995         const char *chip_name;
 996         const char *chip_vers;
 997 
 998         dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
 999         dev->dip = dip;
1000         ddi_set_driver_private(dip, dev);
1001         mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
1002 
1003         if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1004                 audio_dev_warn(dev->osdev, "pci_config_setup failed");
1005                 goto err_exit;
1006         }
1007 
1008         vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1009         device = pci_config_get16(pcih, PCI_CONF_DEVID);
1010         revision = pci_config_get8(pcih, PCI_CONF_REVID);
1011 
1012         if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
1013             (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
1014             device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
1015             device != ENSONIQ_ES5880B)) {
1016                 audio_dev_warn(dev->osdev, "unrecognized device");
1017                 goto err_exit;
1018         }
1019 
1020         chip_name = "AudioPCI97";
1021         chip_vers = "unknown";
1022 
1023         switch (device) {
1024         case ENSONIQ_ES1371:
1025                 chip_name = "AudioPCI97";
1026                 switch (revision) {
1027                 case 0x02:
1028                 case 0x09:
1029                 default:
1030                         chip_vers = "ES1371";
1031                         break;
1032                 case 0x04:
1033                 case 0x06:
1034                 case 0x08:
1035                         chip_vers = "ES1373";
1036                         break;
1037                 case 0x07:
1038                         chip_vers = "ES5880";
1039                         break;
1040                 }
1041                 break;
1042 
1043         case ENSONIQ_ES5880:
1044                 chip_name = "SB PCI128";
1045                 chip_vers = "ES5880";
1046                 break;
1047         case ENSONIQ_ES5880A:
1048                 chip_name = "SB PCI128";
1049                 chip_vers = "ES5880A";
1050                 break;
1051         case ENSONIQ_ES5880B:
1052                 chip_name = "SB PCI128";
1053                 chip_vers = "ES5880B";
1054                 break;
1055 
1056         case ECTIVA_ES1938:
1057                 chip_name = "AudioPCI";
1058                 chip_vers = "ES1938";
1059                 break;
1060         }
1061 
1062         dev->revision = revision;
1063         dev->devid = device;
1064 
1065         dev->osdev = audio_dev_alloc(dip, 0);
1066         if (dev->osdev == NULL) {
1067                 goto err_exit;
1068         }
1069 
1070         audio_dev_set_description(dev->osdev, chip_name);
1071         audio_dev_set_version(dev->osdev, chip_vers);
1072 
1073         /* set the PCI latency */
1074         if ((audioens_latency == 32) || (audioens_latency == 64) ||
1075             (audioens_latency == 96))
1076                 pci_config_put8(pcih, PCI_CONF_LATENCY_TIMER,
1077                     audioens_latency);
1078 
1079         /* activate the device */
1080         pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1081         pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1082         pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1083 
1084         /* map registers */
1085         if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
1086             &dev->acch) != DDI_SUCCESS) {
1087                 audio_dev_warn(dev->osdev, "can't map registers");
1088                 goto err_exit;
1089         }
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 
1110         /* This allocates and configures the engines */
1111         if (audioens_init(dev) != DDI_SUCCESS) {
1112                 audio_dev_warn(dev->osdev, "can't init device");
1113                 goto err_exit;
1114         }
1115 
1116 #ifdef __x86
1117         if (dev->useintr) {
1118                 (void) ddi_intr_enable(dev->intrh);
1119         }
1120 #endif
1121         pci_config_teardown(&pcih);
1122 
1123         ddi_report_dev(dip);
1124 
1125         return (DDI_SUCCESS);
1126 
1127 err_exit:
1128         pci_config_teardown(&pcih);
1129 
1130         audioens_destroy(dev);
1131 
1132         return (DDI_FAILURE);
1133 }
1134 
1135 int
1136 audioens_detach(audioens_dev_t *dev)
1137 {
1138         int tmp;
1139 
1140         /* first unregister us from the DDI framework, might be busy */
1141         if (audio_dev_unregister(dev->osdev) != DDI_SUCCESS)
1142                 return (DDI_FAILURE);
1143 
1144         mutex_enter(&dev->mutex);
1145 
1146         tmp = GET8(dev, CONC_bSERCTL_OFF) &
1147             ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1148         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1149         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1150         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1151         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1152 
1153         tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1154             ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1155         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1156         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1157         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1158         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1159 
1160         mutex_exit(&dev->mutex);
1161 
1162         audioens_destroy(dev);
1163 
1164         return (DDI_SUCCESS);
1165 }
1166 
1167 static int
1168 audioens_resume(audioens_dev_t *dev)
1169 {
1170         mutex_enter(&dev->mutex);
1171         dev->suspended = B_FALSE;
1172         mutex_exit(&dev->mutex);
1173 
1174         /* reinitialize hardware */
1175         audioens_init_hw(dev);
1176 
1177         /* restore AC97 state */
1178         ac97_reset(dev->ac97);
1179 
1180         audio_dev_resume(dev->osdev);
1181 
1182         return (DDI_SUCCESS);
1183 }
1184 
1185 static int
1186 audioens_suspend(audioens_dev_t *dev)
1187 {
1188         audio_dev_suspend(dev->osdev);
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 
1196         return (DDI_SUCCESS);
1197 }
1198 
1199 static int
1200 audioens_quiesce(dev_info_t *dip)
1201 {
1202         audioens_dev_t  *dev;
1203         uint8_t         tmp;
1204 
1205         if ((dev = ddi_get_driver_private(dip)) == NULL) {
1206                 return (DDI_FAILURE);
1207         }
1208 
1209         /* This disables all DMA engines and interrupts */
1210         tmp = GET8(dev, CONC_bSERCTL_OFF) &
1211             ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1212         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1213         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1214         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1215         PUT8(dev, CONC_bSERCTL_OFF, tmp);
1216 
1217         tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1218             ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1219         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1220         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1221         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1222         PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1223 
1224         return (DDI_SUCCESS);
1225 }
1226 
1227 
1228 static int
1229 audioens_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1230 {
1231         audioens_dev_t *dev;
1232 
1233         switch (cmd) {
1234         case DDI_ATTACH:
1235                 return (audioens_attach(dip));
1236 
1237         case DDI_RESUME:
1238                 if ((dev = ddi_get_driver_private(dip)) == NULL) {
1239                         return (DDI_FAILURE);
1240                 }
1241                 return (audioens_resume(dev));
1242 
1243         default:
1244                 return (DDI_FAILURE);
1245         }
1246 }
1247 
1248 static int
1249 audioens_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1250 {
1251         audioens_dev_t *dev;
1252 
1253         if ((dev = ddi_get_driver_private(dip)) == NULL) {
1254                 return (DDI_FAILURE);
1255         }
1256 
1257         switch (cmd) {
1258         case DDI_DETACH:
1259                 return (audioens_detach(dev));
1260 
1261         case DDI_SUSPEND:
1262                 return (audioens_suspend(dev));
1263         default:
1264                 return (DDI_FAILURE);
1265         }
1266 }
1267 
1268 static int audioens_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1269 static int audioens_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1270 
1271 static struct dev_ops audioens_dev_ops = {
1272         DEVO_REV,               /* rev */
1273         0,                      /* refcnt */
1274         NULL,                   /* getinfo */
1275         nulldev,                /* identify */
1276         nulldev,                /* probe */
1277         audioens_ddi_attach,    /* attach */
1278         audioens_ddi_detach,    /* detach */
1279         nodev,                  /* reset */
1280         NULL,                   /* cb_ops */
1281         NULL,                   /* bus_ops */
1282         NULL,                   /* power */
1283         audioens_quiesce,       /* quiesce */
1284 };
1285 
1286 static struct modldrv audioens_modldrv = {
1287         &mod_driverops,                     /* drv_modops */
1288         "Ensoniq 1371/1373 Audio",      /* linkinfo */
1289         &audioens_dev_ops,          /* dev_ops */
1290 };
1291 
1292 static struct modlinkage modlinkage = {
1293         MODREV_1,
1294         { &audioens_modldrv, NULL }
1295 };
1296 
1297 int
1298 _init(void)
1299 {
1300         int     rv;
1301 
1302         audio_init_ops(&audioens_dev_ops, DRVNAME);
1303         if ((rv = mod_install(&modlinkage)) != 0) {
1304                 audio_fini_ops(&audioens_dev_ops);
1305         }
1306         return (rv);
1307 }
1308 
1309 int
1310 _fini(void)
1311 {
1312         int     rv;
1313 
1314         if ((rv = mod_remove(&modlinkage)) == 0) {
1315                 audio_fini_ops(&audioens_dev_ops);
1316         }
1317         return (rv);
1318 }
1319 
1320 int
1321 _info(struct modinfo *modinfop)
1322 {
1323         return (mod_info(&modlinkage, modinfop));
1324 }