xref: /illumos-gate/usr/src/uts/common/io/audio/drv/audioens/audioens.c (revision a92282e44f968185a6bba094d1e5fece2da819cf)
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 	default:
689 		panic("Unknown port number: %d\n", port->num);
690 	}
691 
692 	mutex_enter(&dev->mutex);
693 #ifdef __x86
694 	if (!dev->useintr) {
695 #endif
696 
697 	/*
698 	 * Note that the current frame counter is in the high nybble.
699 	 */
700 	frameno = audioens_readmem(port->dev, page, offs) >> 16;
701 	n = frameno >= port->frameno ?
702 	    frameno - port->frameno :
703 	    frameno + port->nframes - port->frameno;
704 	port->frameno = frameno;
705 	port->count += n;
706 
707 #ifdef __x86
708 	}
709 #endif
710 
711 	val = port->count;
712 	mutex_exit(&dev->mutex);
713 
714 	return (val);
715 }
716 
717 static void
718 audioens_close(void *arg)
719 {
720 	_NOTE(ARGUNUSED(arg));
721 }
722 
723 static void
724 audioens_sync(void *arg, unsigned nframes)
725 {
726 	audioens_port_t *port = arg;
727 
728 	_NOTE(ARGUNUSED(nframes));
729 
730 	if (port->num == PORT_ADC) {
731 		(void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
732 	} else {
733 		(void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
734 	}
735 }
736 
737 static void
738 audioens_chinfo(void *arg, int chan, unsigned *offset, unsigned *incr)
739 {
740 	audioens_port_t *port = arg;
741 
742 	if ((port->num == PORT_DAC) && (chan >= 2)) {
743 		*offset = (port->nframes * 2) + (chan % 2);
744 		*incr = 2;
745 	} else {
746 		*offset = chan;
747 		*incr = 2;
748 	}
749 }
750 
751 audio_engine_ops_t audioens_engine_ops = {
752 	AUDIO_ENGINE_VERSION,		/* version number */
753 	audioens_open,
754 	audioens_close,
755 	audioens_start,
756 	audioens_stop,
757 	audioens_count,
758 	audioens_format,
759 	audioens_channels,
760 	audioens_rate,
761 	audioens_sync,
762 	NULL,
763 	audioens_chinfo,
764 	NULL,
765 };
766 
767 void
768 audioens_init_hw(audioens_dev_t *dev)
769 {
770 	int tmp;
771 
772 	if ((dev->devid == ENSONIQ_ES5880) ||
773 	    (dev->devid == ENSONIQ_ES5880A) ||
774 	    (dev->devid == ENSONIQ_ES5880B) ||
775 	    (dev->devid == 0x1371 && dev->revision == 7) ||
776 	    (dev->devid == 0x1371 && dev->revision >= 9)) {
777 
778 		/* Have a ES5880 so enable the codec manually */
779 		tmp = GET8(dev, CONC_bINTSUMM_OFF) & 0xff;
780 		tmp |= 0x20;
781 		PUT8(dev, CONC_bINTSUMM_OFF, tmp);
782 		for (int i = 0; i < 2000; i++)
783 			drv_usecwait(10);
784 	}
785 
786 	SRCInit(dev);
787 
788 	/*
789 	 * Turn on CODEC (UART and joystick left disabled)
790 	 */
791 	tmp = GET32(dev, CONC_bDEVCTL_OFF) & 0xff;
792 	tmp &= ~(CONC_DEVCTL_PCICLK_DS | CONC_DEVCTL_XTALCLK_DS);
793 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
794 	PUT8(dev, CONC_bUARTCSTAT_OFF, 0x00);
795 
796 	/* Perform AC97 codec warm reset */
797 	tmp = GET8(dev, CONC_bMISCCTL_OFF) & 0xff;
798 	PUT8(dev, CONC_bMISCCTL_OFF, tmp | CONC_MISCCTL_SYNC_RES);
799 	drv_usecwait(200);
800 	PUT8(dev, CONC_bMISCCTL_OFF, tmp);
801 	drv_usecwait(200);
802 
803 	if (dev->revision >= 4) {
804 		/* XXX: enable SPDIF - PCM only for now */
805 		if (audioens_spdif) {
806 			/* enable SPDIF */
807 			PUT32(dev, 0x04, GET32(dev, 0x04) | (1 << 18));
808 			/* SPDIF out = data from DAC */
809 			PUT32(dev, 0x00, GET32(dev, 0x00) | (1 << 26));
810 			CLR32(dev, CONC_dSPDIF_OFF, CONC_SPDIF_AC3);
811 
812 		} else {
813 			/* disable spdif out */
814 			PUT32(dev, 0x04, GET32(dev, 0x04) & ~(1 << 18));
815 			PUT32(dev, 0x00, GET32(dev, 0x00) & ~(1 << 26));
816 		}
817 
818 		/* we want to run each channel independently */
819 		CLR32(dev, CONC_dSTATUS_OFF, CONC_STATUS_ECHO);
820 	}
821 }
822 
823 static int
824 audioens_init(audioens_dev_t *dev)
825 {
826 
827 	audioens_init_hw(dev);
828 
829 	/*
830 	 * On this hardware, we want to disable the internal speaker by
831 	 * default, if it exists.  (We don't have a speakerphone on any
832 	 * of these cards, and no SPARC hardware uses it either!)
833 	 */
834 	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dev->dip, AC97_PROP_SPEAKER,
835 	    0);
836 
837 	/*
838 	 * Init mixer
839 	 */
840 
841 	dev->ac97 = ac97_alloc(dev->dip, audioens_rd97, audioens_wr97, dev);
842 	if (dev->ac97 == NULL)
843 		return (DDI_FAILURE);
844 
845 	if (ac97_init(dev->ac97, dev->osdev) != 0) {
846 		return (DDI_FAILURE);
847 	}
848 
849 	for (int i = 0; i <= PORT_MAX; i++) {
850 		audioens_port_t *port;
851 		unsigned caps;
852 		unsigned dmaflags;
853 		size_t rlen;
854 		ddi_dma_cookie_t c;
855 		unsigned ccnt;
856 		size_t bufsz;
857 
858 		port = &dev->port[i];
859 		port->dev = dev;
860 
861 		/*
862 		 * We have 48000Hz.  At that rate, 128 frames will give
863 		 * us an interrupt rate of 375Hz.  2048 frames buys about
864 		 * 42ms of buffer.  Note that interrupts are only enabled
865 		 * for platforms which need them (i.e. VMWare).
866 		 */
867 
868 		switch (i) {
869 		case PORT_DAC:
870 			port->nchan = 4;
871 			port->speed = 48000;
872 			port->iframes = 128;
873 			port->nframes = 2048;
874 			caps = ENGINE_OUTPUT_CAP;
875 			dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
876 			break;
877 
878 		case PORT_ADC:
879 			port->nchan = 2;
880 			port->speed = 48000;
881 			port->iframes = 128;
882 			port->nframes = 2048;
883 			caps = ENGINE_INPUT_CAP;
884 			dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
885 			break;
886 		}
887 
888 		port->num = i;
889 		bufsz = port->nframes * port->nchan * sizeof (uint16_t);
890 
891 		/*
892 		 * Allocate DMA resources.
893 		 */
894 
895 		if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
896 		    NULL, &port->dmah) != DDI_SUCCESS) {
897 			audio_dev_warn(dev->osdev,
898 			    "port %d: dma handle allocation failed", i);
899 			return (DDI_FAILURE);
900 		}
901 		if (ddi_dma_mem_alloc(port->dmah, bufsz, &buf_attr,
902 		    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
903 		    &rlen, &port->acch) != DDI_SUCCESS) {
904 			audio_dev_warn(dev->osdev,
905 			    "port %d: dma memory allocation failed", i);
906 			return (DDI_FAILURE);
907 		}
908 		/* ensure that the buffer is zeroed out properly */
909 		bzero(port->kaddr, rlen);
910 		if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
911 		    bufsz, dmaflags, DDI_DMA_SLEEP, NULL,
912 		    &c, &ccnt) != DDI_DMA_MAPPED) {
913 			audio_dev_warn(dev->osdev,
914 			    "port %d: dma binding failed", i);
915 			return (DDI_FAILURE);
916 		}
917 		port->paddr = c.dmac_address;
918 
919 		/*
920 		 * Allocate and configure audio engine.
921 		 */
922 		port->engine = audio_engine_alloc(&audioens_engine_ops, caps);
923 		if (port->engine == NULL) {
924 			audio_dev_warn(dev->osdev,
925 			    "port %d: audio_engine_alloc failed", i);
926 			return (DDI_FAILURE);
927 		}
928 
929 		audio_engine_set_private(port->engine, port);
930 		audio_dev_add_engine(dev->osdev, port->engine);
931 	}
932 
933 	if (audio_dev_register(dev->osdev) != DDI_SUCCESS) {
934 		audio_dev_warn(dev->osdev,
935 		    "unable to register with audio framework");
936 		return (DDI_FAILURE);
937 	}
938 
939 	return (DDI_SUCCESS);
940 }
941 
942 void
943 audioens_destroy(audioens_dev_t *dev)
944 {
945 	int	i;
946 
947 #ifdef __x86
948 	if (dev->useintr && dev->intrh != NULL) {
949 		(void) ddi_intr_disable(dev->intrh);
950 		(void) ddi_intr_remove_handler(dev->intrh);
951 		(void) ddi_intr_free(dev->intrh);
952 		dev->intrh = NULL;
953 	}
954 #endif
955 
956 	mutex_destroy(&dev->mutex);
957 
958 	/* free up ports, including DMA resources for ports */
959 	for (i = 0; i <= PORT_MAX; i++) {
960 		audioens_port_t	*port = &dev->port[i];
961 
962 		if (port->paddr != 0)
963 			(void) ddi_dma_unbind_handle(port->dmah);
964 		if (port->acch != NULL)
965 			ddi_dma_mem_free(&port->acch);
966 		if (port->dmah != NULL)
967 			ddi_dma_free_handle(&port->dmah);
968 
969 		if (port->engine != NULL) {
970 			audio_dev_remove_engine(dev->osdev, port->engine);
971 			audio_engine_free(port->engine);
972 		}
973 	}
974 
975 	if (dev->acch != NULL) {
976 		ddi_regs_map_free(&dev->acch);
977 	}
978 
979 	if (dev->ac97) {
980 		ac97_free(dev->ac97);
981 	}
982 
983 	if (dev->osdev != NULL) {
984 		audio_dev_free(dev->osdev);
985 	}
986 
987 	kmem_free(dev, sizeof (*dev));
988 }
989 
990 int
991 audioens_attach(dev_info_t *dip)
992 {
993 	uint16_t pci_command, vendor, device;
994 	uint8_t revision;
995 	audioens_dev_t *dev;
996 	ddi_acc_handle_t pcih;
997 	const char *chip_name;
998 	const char *chip_vers;
999 
1000 	dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
1001 	dev->dip = dip;
1002 	ddi_set_driver_private(dip, dev);
1003 	mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
1004 
1005 	if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
1006 		audio_dev_warn(dev->osdev, "pci_config_setup failed");
1007 		goto err_exit;
1008 	}
1009 
1010 	vendor = pci_config_get16(pcih, PCI_CONF_VENID);
1011 	device = pci_config_get16(pcih, PCI_CONF_DEVID);
1012 	revision = pci_config_get8(pcih, PCI_CONF_REVID);
1013 
1014 	if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
1015 	    (device != ENSONIQ_ES1371 && device != ENSONIQ_ES5880 &&
1016 	    device != ENSONIQ_ES5880A && device != ECTIVA_ES1938 &&
1017 	    device != ENSONIQ_ES5880B)) {
1018 		audio_dev_warn(dev->osdev, "unrecognized device");
1019 		goto err_exit;
1020 	}
1021 
1022 	chip_name = "AudioPCI97";
1023 	chip_vers = "unknown";
1024 
1025 	switch (device) {
1026 	case ENSONIQ_ES1371:
1027 		chip_name = "AudioPCI97";
1028 		switch (revision) {
1029 		case 0x02:
1030 		case 0x09:
1031 		default:
1032 			chip_vers = "ES1371";
1033 			break;
1034 		case 0x04:
1035 		case 0x06:
1036 		case 0x08:
1037 			chip_vers = "ES1373";
1038 			break;
1039 		case 0x07:
1040 			chip_vers = "ES5880";
1041 			break;
1042 		}
1043 		break;
1044 
1045 	case ENSONIQ_ES5880:
1046 		chip_name = "SB PCI128";
1047 		chip_vers = "ES5880";
1048 		break;
1049 	case ENSONIQ_ES5880A:
1050 		chip_name = "SB PCI128";
1051 		chip_vers = "ES5880A";
1052 		break;
1053 	case ENSONIQ_ES5880B:
1054 		chip_name = "SB PCI128";
1055 		chip_vers = "ES5880B";
1056 		break;
1057 
1058 	case ECTIVA_ES1938:
1059 		chip_name = "AudioPCI";
1060 		chip_vers = "ES1938";
1061 		break;
1062 	}
1063 
1064 	dev->revision = revision;
1065 	dev->devid = device;
1066 
1067 	dev->osdev = audio_dev_alloc(dip, 0);
1068 	if (dev->osdev == NULL) {
1069 		goto err_exit;
1070 	}
1071 
1072 	audio_dev_set_description(dev->osdev, chip_name);
1073 	audio_dev_set_version(dev->osdev, chip_vers);
1074 
1075 	/* set the PCI latency */
1076 	if ((audioens_latency == 32) || (audioens_latency == 64) ||
1077 	    (audioens_latency == 96))
1078 		pci_config_put8(pcih, PCI_CONF_LATENCY_TIMER,
1079 		    audioens_latency);
1080 
1081 	/* activate the device */
1082 	pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
1083 	pci_command |= PCI_COMM_ME | PCI_COMM_IO;
1084 	pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
1085 
1086 	/* map registers */
1087 	if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
1088 	    &dev->acch) != DDI_SUCCESS) {
1089 		audio_dev_warn(dev->osdev, "can't map registers");
1090 		goto err_exit;
1091 	}
1092 
1093 #ifdef __x86
1094 	/*
1095 	 * Virtual platforms (mostly VMWare!) seem to need us to pulse
1096 	 * the interrupt enables to make progress.  So enable (emulated)
1097 	 * hardware interrupts.
1098 	 */
1099 	dev->useintr = B_FALSE;
1100 	if (get_hwenv() & HW_VIRTUAL) {
1101 		dev->useintr = B_TRUE;
1102 		if (audioens_setup_intr(dev) != DDI_SUCCESS) {
1103 			goto err_exit;
1104 		}
1105 		/* Reinitialize the mutex with interrupt priority. */
1106 		mutex_destroy(&dev->mutex);
1107 		mutex_init(&dev->mutex, NULL, MUTEX_DRIVER,
1108 		    DDI_INTR_PRI(dev->intrpri));
1109 	}
1110 #endif
1111 
1112 	/* This allocates and configures the engines */
1113 	if (audioens_init(dev) != DDI_SUCCESS) {
1114 		audio_dev_warn(dev->osdev, "can't init device");
1115 		goto err_exit;
1116 	}
1117 
1118 #ifdef __x86
1119 	if (dev->useintr) {
1120 		(void) ddi_intr_enable(dev->intrh);
1121 	}
1122 #endif
1123 	pci_config_teardown(&pcih);
1124 
1125 	ddi_report_dev(dip);
1126 
1127 	return (DDI_SUCCESS);
1128 
1129 err_exit:
1130 	pci_config_teardown(&pcih);
1131 
1132 	audioens_destroy(dev);
1133 
1134 	return (DDI_FAILURE);
1135 }
1136 
1137 int
1138 audioens_detach(audioens_dev_t *dev)
1139 {
1140 	int tmp;
1141 
1142 	/* first unregister us from the DDI framework, might be busy */
1143 	if (audio_dev_unregister(dev->osdev) != DDI_SUCCESS)
1144 		return (DDI_FAILURE);
1145 
1146 	mutex_enter(&dev->mutex);
1147 
1148 	tmp = GET8(dev, CONC_bSERCTL_OFF) &
1149 	    ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1150 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1151 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1152 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1153 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1154 
1155 	tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1156 	    ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1157 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1158 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1159 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1160 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1161 
1162 	mutex_exit(&dev->mutex);
1163 
1164 	audioens_destroy(dev);
1165 
1166 	return (DDI_SUCCESS);
1167 }
1168 
1169 static int
1170 audioens_resume(audioens_dev_t *dev)
1171 {
1172 	mutex_enter(&dev->mutex);
1173 	dev->suspended = B_FALSE;
1174 	mutex_exit(&dev->mutex);
1175 
1176 	/* reinitialize hardware */
1177 	audioens_init_hw(dev);
1178 
1179 	/* restore AC97 state */
1180 	ac97_reset(dev->ac97);
1181 
1182 	audio_dev_resume(dev->osdev);
1183 
1184 	return (DDI_SUCCESS);
1185 }
1186 
1187 static int
1188 audioens_suspend(audioens_dev_t *dev)
1189 {
1190 	audio_dev_suspend(dev->osdev);
1191 
1192 	mutex_enter(&dev->mutex);
1193 	CLR8(dev, CONC_bDEVCTL_OFF,
1194 	    CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_DAC1_EN | CONC_DEVCTL_ADC_EN);
1195 	dev->suspended = B_TRUE;
1196 	mutex_exit(&dev->mutex);
1197 
1198 	return (DDI_SUCCESS);
1199 }
1200 
1201 static int
1202 audioens_quiesce(dev_info_t *dip)
1203 {
1204 	audioens_dev_t	*dev;
1205 	uint8_t		tmp;
1206 
1207 	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1208 		return (DDI_FAILURE);
1209 	}
1210 
1211 	/* This disables all DMA engines and interrupts */
1212 	tmp = GET8(dev, CONC_bSERCTL_OFF) &
1213 	    ~(CONC_SERCTL_DAC2IE | CONC_SERCTL_DAC1IE | CONC_SERCTL_ADCIE);
1214 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1215 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1216 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1217 	PUT8(dev, CONC_bSERCTL_OFF, tmp);
1218 
1219 	tmp = GET8(dev, CONC_bDEVCTL_OFF) &
1220 	    ~(CONC_DEVCTL_DAC2_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_DAC1_EN);
1221 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1222 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1223 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1224 	PUT8(dev, CONC_bDEVCTL_OFF, tmp);
1225 
1226 	return (DDI_SUCCESS);
1227 }
1228 
1229 
1230 static int
1231 audioens_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1232 {
1233 	audioens_dev_t *dev;
1234 
1235 	switch (cmd) {
1236 	case DDI_ATTACH:
1237 		return (audioens_attach(dip));
1238 
1239 	case DDI_RESUME:
1240 		if ((dev = ddi_get_driver_private(dip)) == NULL) {
1241 			return (DDI_FAILURE);
1242 		}
1243 		return (audioens_resume(dev));
1244 
1245 	default:
1246 		return (DDI_FAILURE);
1247 	}
1248 }
1249 
1250 static int
1251 audioens_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1252 {
1253 	audioens_dev_t *dev;
1254 
1255 	if ((dev = ddi_get_driver_private(dip)) == NULL) {
1256 		return (DDI_FAILURE);
1257 	}
1258 
1259 	switch (cmd) {
1260 	case DDI_DETACH:
1261 		return (audioens_detach(dev));
1262 
1263 	case DDI_SUSPEND:
1264 		return (audioens_suspend(dev));
1265 	default:
1266 		return (DDI_FAILURE);
1267 	}
1268 }
1269 
1270 static int audioens_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
1271 static int audioens_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
1272 
1273 static struct dev_ops audioens_dev_ops = {
1274 	DEVO_REV,		/* rev */
1275 	0,			/* refcnt */
1276 	NULL,			/* getinfo */
1277 	nulldev,		/* identify */
1278 	nulldev,		/* probe */
1279 	audioens_ddi_attach,	/* attach */
1280 	audioens_ddi_detach,	/* detach */
1281 	nodev,			/* reset */
1282 	NULL,			/* cb_ops */
1283 	NULL,			/* bus_ops */
1284 	NULL,			/* power */
1285 	audioens_quiesce,	/* quiesce */
1286 };
1287 
1288 static struct modldrv audioens_modldrv = {
1289 	&mod_driverops,			/* drv_modops */
1290 	"Ensoniq 1371/1373 Audio",	/* linkinfo */
1291 	&audioens_dev_ops,		/* dev_ops */
1292 };
1293 
1294 static struct modlinkage modlinkage = {
1295 	MODREV_1,
1296 	{ &audioens_modldrv, NULL }
1297 };
1298 
1299 int
1300 _init(void)
1301 {
1302 	int	rv;
1303 
1304 	audio_init_ops(&audioens_dev_ops, DRVNAME);
1305 	if ((rv = mod_install(&modlinkage)) != 0) {
1306 		audio_fini_ops(&audioens_dev_ops);
1307 	}
1308 	return (rv);
1309 }
1310 
1311 int
1312 _fini(void)
1313 {
1314 	int	rv;
1315 
1316 	if ((rv = mod_remove(&modlinkage)) == 0) {
1317 		audio_fini_ops(&audioens_dev_ops);
1318 	}
1319 	return (rv);
1320 }
1321 
1322 int
1323 _info(struct modinfo *modinfop)
1324 {
1325 	return (mod_info(&modlinkage, modinfop));
1326 }
1327