xref: /illumos-gate/usr/src/uts/common/io/audio/drv/audioixp/audioixp.c (revision 0d166b18feda26f6f45f5be1c0c8c5e539b90e6c)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * audioixp Audio Driver
28  *
29  * This driver supports audio hardware integrated in ATI IXP400 chipset.
30  *
31  * The IXP400 audio core is an AC'97 controller, which has independent
32  * channels for PCM in, PCM out. The AC'97 controller is a PCI bus master
33  * with scatter/gather support. Each channel has a DMA engine. Currently,
34  * we use only the PCM in and PCM out channels. Each DMA engine uses one
35  * buffer descriptor list.  Each entry contains a pointer to a data buffer,
36  * status, length of the buffer being pointed to and the pointer to the next
37  * entry. Length of the buffer is in number of bytes. Interrupt will be
38  * triggered each time a entry is processed by hardware.
39  *
40  * System power management is not yet supported by the driver.
41  *
42  * 	NOTE:
43  * 	This driver depends on the misc/ac97 and drv/audio modules being
44  *	loaded first.
45  */
46 #include <sys/types.h>
47 #include <sys/modctl.h>
48 #include <sys/kmem.h>
49 #include <sys/conf.h>
50 #include <sys/ddi.h>
51 #include <sys/sunddi.h>
52 #include <sys/pci.h>
53 #include <sys/note.h>
54 #include <sys/audio/audio_driver.h>
55 #include <sys/audio/ac97.h>
56 #include "audioixp.h"
57 
58 /*
59  * Module linkage routines for the kernel
60  */
61 static int audioixp_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
62 static int audioixp_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
63 static int audioixp_quiesce(dev_info_t *);
64 static int audioixp_resume(dev_info_t *);
65 static int audioixp_suspend(dev_info_t *);
66 
67 /*
68  * Entry point routine prototypes
69  */
70 static int audioixp_open(void *, int, unsigned *, unsigned *, caddr_t *);
71 static void audioixp_close(void *);
72 static int audioixp_start(void *);
73 static void audioixp_stop(void *);
74 static int audioixp_format(void *);
75 static int audioixp_channels(void *);
76 static int audioixp_rate(void *);
77 static uint64_t audioixp_count(void *);
78 static void audioixp_sync(void *, unsigned);
79 
80 static audio_engine_ops_t audioixp_engine_ops = {
81 	AUDIO_ENGINE_VERSION,
82 	audioixp_open,
83 	audioixp_close,
84 	audioixp_start,
85 	audioixp_stop,
86 	audioixp_count,
87 	audioixp_format,
88 	audioixp_channels,
89 	audioixp_rate,
90 	audioixp_sync,
91 	NULL,
92 	NULL,
93 	NULL
94 };
95 
96 
97 /*
98  * interrupt handler
99  */
100 static uint_t	audioixp_intr(caddr_t);
101 
102 /*
103  * Local Routine Prototypes
104  */
105 static int audioixp_attach(dev_info_t *);
106 static int audioixp_detach(dev_info_t *);
107 static int audioixp_alloc_port(audioixp_state_t *, int);
108 static void audioixp_start_port(audioixp_port_t *);
109 static void audioixp_stop_port(audioixp_port_t *);
110 static void audioixp_reset_port(audioixp_port_t *);
111 static void audioixp_update_port(audioixp_port_t *);
112 
113 static int audioixp_codec_sync(audioixp_state_t *);
114 static void audioixp_wr97(void *, uint8_t, uint16_t);
115 static uint16_t audioixp_rd97(void *, uint8_t);
116 static int audioixp_reset_ac97(audioixp_state_t *);
117 static int audioixp_map_regs(audioixp_state_t *);
118 static void audioixp_unmap_regs(audioixp_state_t *);
119 static int audioixp_chip_init(audioixp_state_t *);
120 static void audioixp_destroy(audioixp_state_t *);
121 
122 /*
123  * Global variables, but used only by this file.
124  */
125 
126 /*
127  * DDI Structures
128  */
129 
130 /* Device operations structure */
131 static struct dev_ops audioixp_dev_ops = {
132 	DEVO_REV,		/* devo_rev */
133 	0,			/* devo_refcnt */
134 	NULL,			/* devo_getinfo */
135 	nulldev,		/* devo_identify - obsolete */
136 	nulldev,		/* devo_probe */
137 	audioixp_ddi_attach,	/* devo_attach */
138 	audioixp_ddi_detach,	/* devo_detach */
139 	nodev,			/* devo_reset */
140 	NULL,			/* devi_cb_ops */
141 	NULL,			/* devo_bus_ops */
142 	NULL,			/* devo_power */
143 	audioixp_quiesce,	/* devo_quiesce */
144 };
145 
146 /* Linkage structure for loadable drivers */
147 static struct modldrv audioixp_modldrv = {
148 	&mod_driverops,		/* drv_modops */
149 	IXP_MOD_NAME,		/* drv_linkinfo */
150 	&audioixp_dev_ops,	/* drv_dev_ops */
151 };
152 
153 /* Module linkage structure */
154 static struct modlinkage audioixp_modlinkage = {
155 	MODREV_1,			/* ml_rev */
156 	(void *)&audioixp_modldrv,	/* ml_linkage */
157 	NULL				/* NULL terminates the list */
158 };
159 
160 /*
161  * device access attributes for register mapping
162  */
163 static struct ddi_device_acc_attr dev_attr = {
164 	DDI_DEVICE_ATTR_V0,
165 	DDI_STRUCTURE_LE_ACC,
166 	DDI_STRICTORDER_ACC
167 };
168 static struct ddi_device_acc_attr buf_attr = {
169 	DDI_DEVICE_ATTR_V0,
170 	DDI_NEVERSWAP_ACC,
171 	DDI_STRICTORDER_ACC
172 };
173 
174 /*
175  * DMA attributes of buffer descriptor list
176  */
177 static ddi_dma_attr_t	bdlist_dma_attr = {
178 	DMA_ATTR_V0,	/* version */
179 	0,		/* addr_lo */
180 	0xffffffff,	/* addr_hi */
181 	0x0000ffff,	/* count_max */
182 	8,		/* align, BDL must be aligned on a 8-byte boundary */
183 	0x3c,		/* burstsize */
184 	8,		/* minxfer, set to the size of a BDlist entry */
185 	0x0000ffff,	/* maxxfer */
186 	0x00000fff,	/* seg, set to the RAM pagesize of intel platform */
187 	1,		/* sgllen, there's no scatter-gather list */
188 	8,		/* granular, set to the value of minxfer */
189 	0		/* flags, use virtual address */
190 };
191 
192 /*
193  * DMA attributes of buffers to be used to receive/send audio data
194  */
195 static ddi_dma_attr_t	sample_buf_dma_attr = {
196 	DMA_ATTR_V0,
197 	0,		/* addr_lo */
198 	0xffffffff,	/* addr_hi */
199 	0x0001fffe,	/* count_max */
200 	4,		/* align, data buffer is aligned on a 2-byte boundary */
201 	0x3c,		/* burstsize */
202 	4,		/* minxfer, set to the size of a sample data */
203 	0x0001ffff,	/* maxxfer */
204 	0x0001ffff,	/* seg */
205 	1,		/* sgllen, no scatter-gather */
206 	4,		/* granular, set to the value of minxfer */
207 	0,		/* flags, use virtual address */
208 };
209 
210 /*
211  * _init()
212  *
213  * Description:
214  *	Driver initialization, called when driver is first loaded.
215  *	This is how access is initially given to all the static structures.
216  *
217  * Arguments:
218  *	None
219  *
220  * Returns:
221  *	ddi_soft_state_init() status, see ddi_soft_state_init(9f), or
222  *	mod_install() status, see mod_install(9f)
223  */
224 int
225 _init(void)
226 {
227 	int	error;
228 
229 	audio_init_ops(&audioixp_dev_ops, IXP_NAME);
230 
231 	if ((error = mod_install(&audioixp_modlinkage)) != 0) {
232 		audio_fini_ops(&audioixp_dev_ops);
233 	}
234 
235 	return (error);
236 }
237 
238 /*
239  * _fini()
240  *
241  * Description:
242  *	Module de-initialization, called when the driver is to be unloaded.
243  *
244  * Arguments:
245  *	None
246  *
247  * Returns:
248  *	mod_remove() status, see mod_remove(9f)
249  */
250 int
251 _fini(void)
252 {
253 	int		error;
254 
255 	if ((error = mod_remove(&audioixp_modlinkage)) != 0) {
256 		return (error);
257 	}
258 
259 	audio_fini_ops(&audioixp_dev_ops);
260 
261 	return (0);
262 }
263 
264 /*
265  * _info()
266  *
267  * Description:
268  *	Module information, returns information about the driver.
269  *
270  * Arguments:
271  *	modinfo		*modinfop	Pointer to the opaque modinfo structure
272  *
273  * Returns:
274  *	mod_info() status, see mod_info(9f)
275  */
276 int
277 _info(struct modinfo *modinfop)
278 {
279 	return (mod_info(&audioixp_modlinkage, modinfop));
280 }
281 
282 
283 /* ******************* Driver Entry Points ********************************* */
284 
285 /*
286  * audioixp_ddi_attach()
287  *
288  * Description:
289  *	Attach an instance of the audioixp driver.
290  *
291  * Arguments:
292  *	dev_info_t	*dip	Pointer to the device's dev_info struct
293  *	ddi_attach_cmd_t cmd	Attach command
294  *
295  * Returns:
296  *	DDI_SUCCESS		The driver was initialized properly
297  *	DDI_FAILURE		The driver couldn't be initialized properly
298  */
299 static int
300 audioixp_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
301 {
302 	switch (cmd) {
303 	case DDI_ATTACH:
304 		return (audioixp_attach(dip));
305 
306 	/*
307 	 * now, no suspend/resume supported. we'll do it in the future.
308 	 */
309 	case DDI_RESUME:
310 		return (audioixp_resume(dip));
311 	default:
312 		return (DDI_FAILURE);
313 	}
314 }
315 
316 /*
317  * audioixp_ddi_detach()
318  *
319  * Description:
320  *	Detach an instance of the audioixp driver.
321  *
322  * Arguments:
323  *	dev_info_t		*dip	Pointer to the device's dev_info struct
324  *	ddi_detach_cmd_t	cmd	Detach command
325  *
326  * Returns:
327  *	DDI_SUCCESS	The driver was detached
328  *	DDI_FAILURE	The driver couldn't be detached
329  */
330 static int
331 audioixp_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
332 {
333 	switch (cmd) {
334 	case DDI_DETACH:
335 		return (audioixp_detach(dip));
336 
337 	/*
338 	 * now, no suspend/resume supported. we'll do it in the future.
339 	 */
340 	case DDI_SUSPEND:
341 		return (audioixp_suspend(dip));
342 
343 	default:
344 		return (DDI_FAILURE);
345 	}
346 }
347 
348 static void
349 audioixp_stop_dma(audioixp_state_t *statep)
350 {
351 	CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT_DMA);
352 	CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN_DMA);
353 }
354 
355 static void
356 audioixp_disable_intr(audioixp_state_t *statep)
357 {
358 	PUT32(IXP_AUDIO_INT, GET32(IXP_AUDIO_INT));
359 	PUT32(IXP_AUDIO_INT_EN, 0);
360 }
361 
362 /*
363  * quiesce(9E) entry point.
364  *
365  * This function is called when the system is single-threaded at high
366  * PIL with preemption disabled. Therefore, this function must not be blocked.
367  *
368  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
369  * DDI_FAILURE indicates an error condition and should almost never happen.
370  */
371 static int
372 audioixp_quiesce(dev_info_t *dip)
373 {
374 	audioixp_state_t		*statep;
375 
376 	statep = ddi_get_driver_private(dip);
377 	ASSERT(statep != NULL);
378 
379 	/* disable HW interrupt */
380 	audioixp_disable_intr(statep);
381 
382 	/* stop DMA engines */
383 	audioixp_stop_dma(statep);
384 
385 	return (DDI_SUCCESS);
386 }
387 
388 static int
389 audioixp_suspend(dev_info_t *dip)
390 {
391 	audioixp_state_t		*statep;
392 
393 	statep = ddi_get_driver_private(dip);
394 	ASSERT(statep != NULL);
395 
396 	ac97_suspend(statep->ac97);
397 	mutex_enter(&statep->inst_lock);
398 
399 	statep->suspended = B_TRUE;
400 
401 	audioixp_disable_intr(statep);
402 	audioixp_stop_dma(statep);
403 
404 	mutex_exit(&statep->inst_lock);
405 	return (DDI_SUCCESS);
406 }
407 
408 static void
409 audioixp_resume_port(audioixp_port_t *port)
410 {
411 	if (port != NULL) {
412 		if (port->engine != NULL) {
413 			audio_engine_reset(port->engine);
414 		}
415 	}
416 	audioixp_reset_port(port);
417 	if (port->started) {
418 		audioixp_start_port(port);
419 	} else {
420 		audioixp_stop_port(port);
421 	}
422 }
423 
424 static int
425 audioixp_resume(dev_info_t *dip)
426 {
427 	audioixp_state_t		*statep;
428 	audio_dev_t			*adev;
429 	audioixp_port_t			*rec_port, *play_port;
430 
431 	statep = ddi_get_driver_private(dip);
432 	adev = statep->adev;
433 	ASSERT(statep != NULL);
434 
435 	if (audioixp_chip_init(statep) != DDI_SUCCESS) {
436 		audio_dev_warn(adev, "DDI_RESUME failed to init chip");
437 		return (DDI_SUCCESS);
438 	}
439 
440 	ac97_resume(statep->ac97);
441 	mutex_enter(&statep->inst_lock);
442 	statep->suspended = B_FALSE;
443 
444 	rec_port = statep->rec_port;
445 	play_port = statep->play_port;
446 
447 	audioixp_resume_port(rec_port);
448 	audioixp_resume_port(play_port);
449 
450 	mutex_exit(&statep->inst_lock);
451 	return (DDI_SUCCESS);
452 }
453 /*
454  * audioixp_intr()
455  *
456  * Description:
457  *	Interrupt service routine for both play and record. For play we
458  *	get the next buffers worth of audio. For record we send it on to
459  *	the mixer.
460  *
461  *	There's a hardware pointer which indicate memory location where
462  *	the hardware is processing. We check this pointer to decide whether
463  *	to handle the buffer and how many buffers should be handled.
464  *	Refer to ATI IXP400/450 Register Reference Manual, page 193,194.
465  *
466  * Arguments:
467  *	caddr_t		arg	Pointer to the interrupting device's state
468  *				structure
469  *
470  * Returns:
471  *	DDI_INTR_CLAIMED	Interrupt claimed and processed
472  *	DDI_INTR_UNCLAIMED	Interrupt not claimed, and thus ignored
473  */
474 static uint_t
475 audioixp_intr(caddr_t arg)
476 {
477 	audioixp_state_t	*statep;
478 	uint32_t		sr;
479 	int			claimed = DDI_INTR_UNCLAIMED;
480 
481 	statep = (void *)arg;
482 	mutex_enter(&statep->inst_lock);
483 
484 	sr = GET32(IXP_AUDIO_INT);
485 
486 	/* PCM in interrupt */
487 	if (sr & IXP_AUDIO_INT_IN_DMA) {
488 		claimed = DDI_INTR_CLAIMED;
489 		PUT32(IXP_AUDIO_INT, IXP_AUDIO_INT_IN_DMA);
490 	}
491 
492 	/* PCM out interrupt */
493 	if (sr & IXP_AUDIO_INT_OUT_DMA) {
494 		claimed = DDI_INTR_CLAIMED;
495 		PUT32(IXP_AUDIO_INT, IXP_AUDIO_INT_OUT_DMA);
496 	}
497 
498 	/* system is too busy to process the input stream, ignore it */
499 	if (sr & IXP_AUDIO_INT_IN_DMA_OVERFLOW) {
500 		claimed = DDI_INTR_CLAIMED;
501 		PUT32(IXP_AUDIO_INT, IXP_AUDIO_INT_IN_DMA_OVERFLOW);
502 	}
503 
504 	/* System is too busy, ignore it */
505 	if (sr & IXP_AUDIO_INT_OUT_DMA_UNDERFLOW) {
506 		claimed = DDI_INTR_CLAIMED;
507 		PUT32(IXP_AUDIO_INT, IXP_AUDIO_INT_OUT_DMA_UNDERFLOW);
508 	}
509 
510 	/* update the kernel interrupt statistics */
511 	if ((claimed == DDI_INTR_CLAIMED) && statep->ksp) {
512 		IXP_KIOP(statep)->intrs[KSTAT_INTR_HARD]++;
513 	}
514 
515 	mutex_exit(&statep->inst_lock);
516 
517 	if (sr & IXP_AUDIO_INT_IN_DMA) {
518 		audio_engine_produce(statep->rec_port->engine);
519 	}
520 	if (sr & IXP_AUDIO_INT_OUT_DMA) {
521 		audio_engine_consume(statep->play_port->engine);
522 	}
523 
524 	return (claimed);
525 }
526 
527 /*
528  * audioixp_open()
529  *
530  * Description:
531  *	Opens a DMA engine for use.
532  *
533  * Arguments:
534  *	void		*arg		The DMA engine to set up
535  *	int		flag		Open flags
536  *	unsigned	*fragfrp	Receives number of frames per fragment
537  *	unsigned	*nfragsp	Receives number of fragments
538  *	caddr_t		*bufp		Receives kernel data buffer
539  *
540  * Returns:
541  *	0	on success
542  *	errno	on failure
543  */
544 static int
545 audioixp_open(void *arg, int flag,
546     unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp)
547 {
548 	audioixp_port_t	*port = arg;
549 
550 	_NOTE(ARGUNUSED(flag));
551 
552 	port->started = B_FALSE;
553 	port->count = 0;
554 	port->offset = 0;
555 	*fragfrp = port->fragfr;
556 	*nfragsp = IXP_BD_NUMS;
557 	*bufp = port->samp_kaddr;
558 
559 	mutex_enter(&port->statep->inst_lock);
560 	audioixp_reset_port(port);
561 	mutex_exit(&port->statep->inst_lock);
562 
563 	return (0);
564 }
565 
566 /*
567  * audioixp_close()
568  *
569  * Description:
570  *	Closes an audio DMA engine that was previously opened.  Since
571  *	nobody is using it, we take this opportunity to possibly power
572  *	down the entire device.
573  *
574  * Arguments:
575  *	void	*arg		The DMA engine to shut down
576  */
577 static void
578 audioixp_close(void *arg)
579 {
580 	audioixp_port_t		*port = arg;
581 	audioixp_state_t	*statep = port->statep;
582 
583 	mutex_enter(&statep->inst_lock);
584 	audioixp_stop_port(port);
585 	port->started = B_FALSE;
586 	mutex_exit(&statep->inst_lock);
587 }
588 
589 /*
590  * audioixp_stop()
591  *
592  * Description:
593  *	This is called by the framework to stop a port that is
594  *	transferring data.
595  *
596  * Arguments:
597  *	void	*arg		The DMA engine to stop
598  */
599 static void
600 audioixp_stop(void *arg)
601 {
602 	audioixp_port_t		*port = arg;
603 	audioixp_state_t	*statep = port->statep;
604 
605 	mutex_enter(&statep->inst_lock);
606 	if (port->started) {
607 		audioixp_stop_port(port);
608 	}
609 	port->started = B_FALSE;
610 	mutex_exit(&statep->inst_lock);
611 }
612 
613 /*
614  * audioixp_start()
615  *
616  * Description:
617  *	This is called by the framework to start a port transferring data.
618  *
619  * Arguments:
620  *	void	*arg		The DMA engine to start
621  *
622  * Returns:
623  *	0 	on success (never fails, errno if it did)
624  */
625 static int
626 audioixp_start(void *arg)
627 {
628 	audioixp_port_t		*port = arg;
629 	audioixp_state_t	*statep = port->statep;
630 
631 	mutex_enter(&statep->inst_lock);
632 	if (!port->started) {
633 		audioixp_start_port(port);
634 		port->started = B_TRUE;
635 	}
636 	mutex_exit(&statep->inst_lock);
637 	return (0);
638 }
639 
640 /*
641  * audioixp_format()
642  *
643  * Description:
644  *	This is called by the framework to query the format for the device.
645  *
646  * Arguments:
647  *	void	*arg		The DMA engine to query
648  *
649  * Returns:
650  *	AUDIO_FORMAT_S16_LE
651  */
652 static int
653 audioixp_format(void *arg)
654 {
655 	_NOTE(ARGUNUSED(arg));
656 
657 	return (AUDIO_FORMAT_S16_LE);
658 }
659 
660 /*
661  * audioixp_channels()
662  *
663  * Description:
664  *	This is called by the framework to query the channels for the device.
665  *
666  * Arguments:
667  *	void	*arg		The DMA engine to query
668  *
669  * Returns:
670  *	Number of channels for the device.
671  */
672 static int
673 audioixp_channels(void *arg)
674 {
675 	audioixp_port_t *port = arg;
676 
677 	return (port->nchan);
678 }
679 
680 /*
681  * audioixp_rate()
682  *
683  * Description:
684  *	This is called by the framework to query the rate of the device.
685  *
686  * Arguments:
687  *	void	*arg		The DMA engine to query
688  *
689  * Returns:
690  *	48000
691  */
692 static int
693 audioixp_rate(void *arg)
694 {
695 	_NOTE(ARGUNUSED(arg));
696 
697 	return (48000);
698 }
699 
700 /*
701  * audioixp_count()
702  *
703  * Description:
704  *	This is called by the framework to get the engine's frame counter
705  *
706  * Arguments:
707  *	void	*arg		The DMA engine to query
708  *
709  * Returns:
710  *	frame count for current engine
711  */
712 static uint64_t
713 audioixp_count(void *arg)
714 {
715 	audioixp_port_t		*port = arg;
716 	audioixp_state_t	*statep = port->statep;
717 	uint64_t		val;
718 
719 	mutex_enter(&statep->inst_lock);
720 	audioixp_update_port(port);
721 	val = port->count;
722 	mutex_exit(&statep->inst_lock);
723 
724 	return (val);
725 }
726 
727 /*
728  * audioixp_sync()
729  *
730  * Description:
731  *	This is called by the framework to synchronize DMA caches.
732  *
733  * Arguments:
734  *	void	*arg		The DMA engine to sync
735  */
736 static void
737 audioixp_sync(void *arg, unsigned nframes)
738 {
739 	audioixp_port_t *port = arg;
740 	_NOTE(ARGUNUSED(nframes));
741 
742 	(void) ddi_dma_sync(port->samp_dmah, 0, 0, port->sync_dir);
743 }
744 
745 /* *********************** Local Routines *************************** */
746 
747 /*
748  * audioixp_alloc_port()
749  *
750  * Description:
751  *	This routine allocates the DMA handles and the memory for the
752  *	DMA engines to use.  It also configures the BDL lists properly
753  *	for use.
754  *
755  * Arguments:
756  *	dev_info_t	*dip	Pointer to the device's devinfo
757  *
758  * Returns:
759  *	DDI_SUCCESS		Registers successfully mapped
760  *	DDI_FAILURE		Registers not successfully mapped
761  */
762 static int
763 audioixp_alloc_port(audioixp_state_t *statep, int num)
764 {
765 	ddi_dma_cookie_t	cookie;
766 	uint_t			count;
767 	int			dir;
768 	unsigned		caps;
769 	char			*prop;
770 	audio_dev_t		*adev;
771 	audioixp_port_t		*port;
772 	uint32_t		paddr;
773 	int			rc;
774 	dev_info_t		*dip;
775 	audioixp_bd_entry_t	*bdentry;
776 
777 	adev = statep->adev;
778 	dip = statep->dip;
779 
780 	port = kmem_zalloc(sizeof (*port), KM_SLEEP);
781 	port->statep = statep;
782 	port->started = B_FALSE;
783 	port->num = num;
784 
785 	switch (num) {
786 	case IXP_REC:
787 		statep->rec_port = port;
788 		prop = "record-interrupts";
789 		dir = DDI_DMA_READ;
790 		caps = ENGINE_INPUT_CAP;
791 		port->sync_dir = DDI_DMA_SYNC_FORKERNEL;
792 		port->nchan = 2;
793 		break;
794 	case IXP_PLAY:
795 		statep->play_port = port;
796 		prop = "play-interrupts";
797 		dir = DDI_DMA_WRITE;
798 		caps = ENGINE_OUTPUT_CAP;
799 		port->sync_dir = DDI_DMA_SYNC_FORDEV;
800 		/* This could possibly be conditionalized */
801 		port->nchan = 6;
802 		break;
803 	default:
804 		audio_dev_warn(adev, "bad port number (%d)!", num);
805 		return (DDI_FAILURE);
806 	}
807 
808 	port->intrs = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
809 	    DDI_PROP_DONTPASS, prop, IXP_INTS);
810 
811 	/* make sure the values are good */
812 	if (port->intrs < IXP_MIN_INTS) {
813 		audio_dev_warn(adev, "%s too low, %d, resetting to %d",
814 		    prop, port->intrs, IXP_INTS);
815 		port->intrs = IXP_INTS;
816 	} else if (port->intrs > IXP_MAX_INTS) {
817 		audio_dev_warn(adev, "%s too high, %d, resetting to %d",
818 		    prop, port->intrs, IXP_INTS);
819 		port->intrs = IXP_INTS;
820 	}
821 
822 	/*
823 	 * Figure out how much space we need.  Sample rate is 48kHz, and
824 	 * we need to store 8 chunks.  (Note that this means that low
825 	 * interrupt frequencies will require more RAM.)
826 	 */
827 	port->fragfr = 48000 / port->intrs;
828 	port->fragfr = IXP_ROUNDUP(port->fragfr, IXP_MOD_SIZE);
829 	port->fragsz = port->fragfr * port->nchan * 2;
830 	port->samp_size = port->fragsz * IXP_BD_NUMS;
831 
832 	/* allocate dma handle */
833 	rc = ddi_dma_alloc_handle(dip, &sample_buf_dma_attr, DDI_DMA_SLEEP,
834 	    NULL, &port->samp_dmah);
835 	if (rc != DDI_SUCCESS) {
836 		audio_dev_warn(adev, "ddi_dma_alloc_handle failed: %d", rc);
837 		return (DDI_FAILURE);
838 	}
839 	/* allocate DMA buffer */
840 	rc = ddi_dma_mem_alloc(port->samp_dmah, port->samp_size, &buf_attr,
841 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->samp_kaddr,
842 	    &port->samp_size, &port->samp_acch);
843 	if (rc == DDI_FAILURE) {
844 		audio_dev_warn(adev, "dma_mem_alloc failed");
845 		return (DDI_FAILURE);
846 	}
847 
848 	/* bind DMA buffer */
849 	rc = ddi_dma_addr_bind_handle(port->samp_dmah, NULL,
850 	    port->samp_kaddr, port->samp_size, dir|DDI_DMA_CONSISTENT,
851 	    DDI_DMA_SLEEP, NULL, &cookie, &count);
852 	if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
853 		audio_dev_warn(adev,
854 		    "ddi_dma_addr_bind_handle failed: %d", rc);
855 		return (DDI_FAILURE);
856 	}
857 	port->samp_paddr = cookie.dmac_address;
858 
859 	/*
860 	 * now, from here we allocate DMA memory for buffer descriptor list.
861 	 * we allocate adjacent DMA memory for all DMA engines.
862 	 */
863 	rc = ddi_dma_alloc_handle(dip, &bdlist_dma_attr, DDI_DMA_SLEEP,
864 	    NULL, &port->bdl_dmah);
865 	if (rc != DDI_SUCCESS) {
866 		audio_dev_warn(adev, "ddi_dma_alloc_handle(bdlist) failed");
867 		return (DDI_FAILURE);
868 	}
869 
870 	/*
871 	 * we allocate all buffer descriptors lists in continuous dma memory.
872 	 */
873 	port->bdl_size = sizeof (audioixp_bd_entry_t) * IXP_BD_NUMS;
874 	rc = ddi_dma_mem_alloc(port->bdl_dmah, port->bdl_size,
875 	    &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
876 	    &port->bdl_kaddr, &port->bdl_size, &port->bdl_acch);
877 	if (rc != DDI_SUCCESS) {
878 		audio_dev_warn(adev, "ddi_dma_mem_alloc(bdlist) failed");
879 		return (DDI_FAILURE);
880 	}
881 
882 	rc = ddi_dma_addr_bind_handle(port->bdl_dmah, NULL, port->bdl_kaddr,
883 	    port->bdl_size, DDI_DMA_WRITE|DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
884 	    NULL, &cookie, &count);
885 	if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
886 		audio_dev_warn(adev, "addr_bind_handle failed");
887 		return (DDI_FAILURE);
888 	}
889 	port->bdl_paddr = cookie.dmac_address;
890 
891 	/*
892 	 * Wire up the BD list.
893 	 */
894 	paddr = port->samp_paddr;
895 	bdentry = (void *)port->bdl_kaddr;
896 
897 	for (int i = 0; i < IXP_BD_NUMS; i++) {
898 
899 		/* set base address of buffer */
900 		ddi_put32(port->bdl_acch, &bdentry->buf_base, paddr);
901 		ddi_put16(port->bdl_acch, &bdentry->status, 0);
902 		ddi_put16(port->bdl_acch, &bdentry->buf_len, port->fragsz / 4);
903 		ddi_put32(port->bdl_acch, &bdentry->next, port->bdl_paddr +
904 		    (((i + 1) % IXP_BD_NUMS) * sizeof (audioixp_bd_entry_t)));
905 		paddr += port->fragsz;
906 		bdentry++;
907 	}
908 	(void) ddi_dma_sync(port->bdl_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
909 
910 	port->engine = audio_engine_alloc(&audioixp_engine_ops, caps);
911 	if (port->engine == NULL) {
912 		audio_dev_warn(adev, "audio_engine_alloc failed");
913 		return (DDI_FAILURE);
914 	}
915 
916 	audio_engine_set_private(port->engine, port);
917 	audio_dev_add_engine(adev, port->engine);
918 
919 	return (DDI_SUCCESS);
920 }
921 
922 /*
923  * audioixp_free_port()
924  *
925  * Description:
926  *	This routine unbinds the DMA cookies, frees the DMA buffers,
927  *	deallocates the DMA handles.
928  *
929  * Arguments:
930  *	audioixp_port_t	*port	The port structure for a DMA engine.
931  */
932 static void
933 audioixp_free_port(audioixp_port_t *port)
934 {
935 	if (port == NULL)
936 		return;
937 
938 	if (port->engine) {
939 		audio_dev_remove_engine(port->statep->adev, port->engine);
940 		audio_engine_free(port->engine);
941 	}
942 	if (port->bdl_paddr) {
943 		(void) ddi_dma_unbind_handle(port->bdl_dmah);
944 	}
945 	if (port->bdl_acch) {
946 		ddi_dma_mem_free(&port->bdl_acch);
947 	}
948 	if (port->bdl_dmah) {
949 		ddi_dma_free_handle(&port->bdl_dmah);
950 	}
951 	if (port->samp_paddr) {
952 		(void) ddi_dma_unbind_handle(port->samp_dmah);
953 	}
954 	if (port->samp_acch) {
955 		ddi_dma_mem_free(&port->samp_acch);
956 	}
957 	if (port->samp_dmah) {
958 		ddi_dma_free_handle(&port->samp_dmah);
959 	}
960 	kmem_free(port, sizeof (*port));
961 }
962 
963 /*
964  * audioixp_start_port()
965  *
966  * Description:
967  *	This routine starts the DMA engine.
968  *
969  * Arguments:
970  *	audioixp_port_t	*port		Port of DMA engine to start.
971  */
972 static void
973 audioixp_start_port(audioixp_port_t *port)
974 {
975 	audioixp_state_t	*statep = port->statep;
976 
977 	ASSERT(mutex_owned(&statep->inst_lock));
978 
979 	/* if suspended, then do nothing else */
980 	if (statep->suspended) {
981 		return;
982 	}
983 
984 	if (port->num == IXP_REC) {
985 		SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN);
986 	} else {
987 		SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT);
988 	}
989 }
990 
991 /*
992  * audioixp_stop_port()
993  *
994  * Description:
995  *	This routine stops the DMA engine.
996  *
997  * Arguments:
998  *	audioixp_port_t	*port		Port of DMA engine to stop.
999  */
1000 static void
1001 audioixp_stop_port(audioixp_port_t *port)
1002 {
1003 	audioixp_state_t	*statep = port->statep;
1004 
1005 	ASSERT(mutex_owned(&statep->inst_lock));
1006 
1007 	/* if suspended, then do nothing else */
1008 	if (statep->suspended) {
1009 		return;
1010 	}
1011 	if (port->num == IXP_REC) {
1012 		CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN);
1013 	} else {
1014 		CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT);
1015 	}
1016 }
1017 
1018 /*
1019  * audioixp_reset_port()
1020  *
1021  * Description:
1022  *	This routine resets the DMA engine pareparing it for work.
1023  *
1024  * Arguments:
1025  *	audioixp_port_t	*port		Port of DMA engine to reset.
1026  */
1027 static void
1028 audioixp_reset_port(audioixp_port_t *port)
1029 {
1030 	audioixp_state_t	*statep = port->statep;
1031 
1032 	ASSERT(mutex_owned(&statep->inst_lock));
1033 
1034 	/*
1035 	 * XXX: reset counters.
1036 	 */
1037 	port->count = 0;
1038 
1039 	if (statep->suspended)
1040 		return;
1041 
1042 	/*
1043 	 * Perform full reset of the engine, and enable its interrupts
1044 	 * but leave it turned off.
1045 	 */
1046 	if (port->num == IXP_REC) {
1047 		PUT32(IXP_AUDIO_FIFO_FLUSH, IXP_AUDIO_FIFO_FLUSH_IN);
1048 		SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_INTER_IN);
1049 
1050 		SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN_DMA);
1051 		PUT32(IXP_AUDIO_IN_DMA_LINK_P,
1052 		    port->bdl_paddr | IXP_AUDIO_IN_DMA_LINK_P_EN);
1053 
1054 	} else {
1055 		uint32_t slot = GET32(IXP_AUDIO_OUT_DMA_SLOT_EN_THRESHOLD);
1056 		PUT32(IXP_AUDIO_FIFO_FLUSH, IXP_AUDIO_FIFO_FLUSH_OUT);
1057 		/* clear all slots */
1058 		slot &= ~ (IXP_AUDIO_OUT_DMA_SLOT_3 |
1059 		    IXP_AUDIO_OUT_DMA_SLOT_4 |
1060 		    IXP_AUDIO_OUT_DMA_SLOT_5 |
1061 		    IXP_AUDIO_OUT_DMA_SLOT_6 |
1062 		    IXP_AUDIO_OUT_DMA_SLOT_7 |
1063 		    IXP_AUDIO_OUT_DMA_SLOT_8 |
1064 		    IXP_AUDIO_OUT_DMA_SLOT_9 |
1065 		    IXP_AUDIO_OUT_DMA_SLOT_10 |
1066 		    IXP_AUDIO_OUT_DMA_SLOT_11 |
1067 		    IXP_AUDIO_OUT_DMA_SLOT_12);
1068 		/* enable 6 channel out, unconditional for now */
1069 		slot |= IXP_AUDIO_OUT_DMA_SLOT_3 |
1070 		    IXP_AUDIO_OUT_DMA_SLOT_4 |
1071 		    IXP_AUDIO_OUT_DMA_SLOT_6 |
1072 		    IXP_AUDIO_OUT_DMA_SLOT_9 |
1073 		    IXP_AUDIO_OUT_DMA_SLOT_7 |
1074 		    IXP_AUDIO_OUT_DMA_SLOT_8;
1075 
1076 		PUT32(IXP_AUDIO_OUT_DMA_SLOT_EN_THRESHOLD, slot);
1077 
1078 		SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_INTER_OUT);
1079 
1080 		SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT_DMA);
1081 		PUT32(IXP_AUDIO_OUT_DMA_LINK_P,
1082 		    port->bdl_paddr | IXP_AUDIO_OUT_DMA_LINK_P_EN);
1083 	}
1084 }
1085 
1086 /*
1087  * audioixp_update_port()
1088  *
1089  * Description:
1090  *	This routine updates the ports frame counter from hardware, and
1091  *	gracefully handles wraps.
1092  *
1093  * Arguments:
1094  *	audioixp_port_t	*port		The port to update.
1095  */
1096 static void
1097 audioixp_update_port(audioixp_port_t *port)
1098 {
1099 	audioixp_state_t	*statep = port->statep;
1100 	unsigned		regoff;
1101 	unsigned		n;
1102 	int			loop;
1103 	uint32_t		offset;
1104 	uint32_t		paddr;
1105 
1106 	if (statep->suspended) {
1107 		return;
1108 	}
1109 	if (port->num == IXP_REC) {
1110 		regoff = IXP_AUDIO_IN_DMA_DT_CUR;
1111 	} else {
1112 		regoff = IXP_AUDIO_OUT_DMA_DT_CUR;
1113 	}
1114 
1115 	/*
1116 	 * Apparently it may take several tries to get an update on the
1117 	 * position.  Is this a hardware bug?
1118 	 */
1119 	for (loop = 100; loop; loop--) {
1120 		paddr = GET32(regoff);
1121 
1122 		/* make sure address is reasonable */
1123 		if ((paddr < port->samp_paddr) ||
1124 		    (paddr >= (port->samp_paddr + port->samp_size))) {
1125 			continue;
1126 		}
1127 
1128 		offset = paddr - port->samp_paddr;
1129 
1130 		if (offset >= port->offset) {
1131 			n = offset - port->offset;
1132 		} else {
1133 			n = offset + (port->samp_size - port->offset);
1134 		}
1135 		port->offset = offset;
1136 		port->count += (n / (port->nchan * sizeof (uint16_t)));
1137 		return;
1138 	}
1139 
1140 	audio_dev_warn(statep->adev, "Unable to update count (h/w bug?)");
1141 }
1142 
1143 
1144 /*
1145  * audioixp_map_regs()
1146  *
1147  * Description:
1148  *	The registers are mapped in.
1149  *
1150  * Arguments:
1151  *	audioixp_state_t	*state		  The device's state structure
1152  *
1153  * Returns:
1154  *	DDI_SUCCESS		Registers successfully mapped
1155  *	DDI_FAILURE		Registers not successfully mapped
1156  */
1157 static int
1158 audioixp_map_regs(audioixp_state_t *statep)
1159 {
1160 	dev_info_t		*dip = statep->dip;
1161 
1162 	/* map PCI config space */
1163 	if (pci_config_setup(statep->dip, &statep->pcih) == DDI_FAILURE) {
1164 		audio_dev_warn(statep->adev, "unable to map PCI config space");
1165 		return (DDI_FAILURE);
1166 	}
1167 
1168 	/* map audio mixer register */
1169 	if ((ddi_regs_map_setup(dip, IXP_IO_AM_REGS, &statep->regsp, 0, 0,
1170 	    &dev_attr, &statep->regsh)) != DDI_SUCCESS) {
1171 		audio_dev_warn(statep->adev, "unable to map audio registers");
1172 		return (DDI_FAILURE);
1173 	}
1174 	return (DDI_SUCCESS);
1175 }
1176 
1177 /*
1178  * audioixp_unmap_regs()
1179  *
1180  * Description:
1181  *	This routine unmaps control registers.
1182  *
1183  * Arguments:
1184  *	audioixp_state_t	*state		The device's state structure
1185  */
1186 static void
1187 audioixp_unmap_regs(audioixp_state_t *statep)
1188 {
1189 	if (statep->regsh) {
1190 		ddi_regs_map_free(&statep->regsh);
1191 	}
1192 
1193 	if (statep->pcih) {
1194 		pci_config_teardown(&statep->pcih);
1195 	}
1196 }
1197 
1198 /*
1199  * audioixp_codec_ready()
1200  *
1201  * Description:
1202  *	This routine checks the state of codecs.  It checks the flag to confirm
1203  *	that primary codec is ready.
1204  *
1205  * Arguments:
1206  *	audioixp_state_t	*state		The device's state structure
1207  *
1208  * Returns:
1209  *	DDI_SUCCESS	 codec is ready
1210  *	DDI_FAILURE	 codec is not ready
1211  */
1212 static int
1213 audioixp_codec_ready(audioixp_state_t *statep)
1214 {
1215 	uint32_t	sr;
1216 
1217 	PUT32(IXP_AUDIO_INT, 0xffffffff);
1218 	drv_usecwait(1000);
1219 
1220 	sr = GET32(IXP_AUDIO_INT);
1221 	if (sr & IXP_AUDIO_INT_CODEC0_NOT_READY) {
1222 		PUT32(IXP_AUDIO_INT, IXP_AUDIO_INT_CODEC0_NOT_READY);
1223 		audio_dev_warn(statep->adev, "primary codec not ready");
1224 
1225 		return (DDI_FAILURE);
1226 	}
1227 	return (DDI_SUCCESS);
1228 }
1229 
1230 /*
1231  * audioixp_codec_sync()
1232  *
1233  * Description:
1234  *	Serialize access to the AC97 audio mixer registers.
1235  *
1236  * Arguments:
1237  *	audioixp_state_t	*state		The device's state structure
1238  *
1239  * Returns:
1240  *	DDI_SUCCESS		Ready for an I/O access to the codec
1241  *	DDI_FAILURE		An I/O access is currently in progress, can't
1242  *				perform another I/O access.
1243  */
1244 static int
1245 audioixp_codec_sync(audioixp_state_t *statep)
1246 {
1247 	int 		i;
1248 	uint32_t	cmd;
1249 
1250 	for (i = 0; i < 300; i++) {
1251 		cmd = GET32(IXP_AUDIO_OUT_PHY_ADDR_DATA);
1252 		if (!(cmd & IXP_AUDIO_OUT_PHY_EN)) {
1253 			return (DDI_SUCCESS);
1254 		}
1255 		drv_usecwait(10);
1256 	}
1257 
1258 	audio_dev_warn(statep->adev, "unable to synchronize codec");
1259 	return (DDI_FAILURE);
1260 }
1261 
1262 /*
1263  * audioixp_rd97()
1264  *
1265  * Description:
1266  *	Get the specific AC97 Codec register.
1267  *
1268  * Arguments:
1269  *	void		*arg		The device's state structure
1270  *	uint8_t		reg		AC97 register number
1271  *
1272  * Returns:
1273  *	Register value.
1274  */
1275 static uint16_t
1276 audioixp_rd97(void *arg, uint8_t reg)
1277 {
1278 	audioixp_state_t	*statep = arg;
1279 	uint32_t		value;
1280 	uint32_t		result;
1281 
1282 	if (audioixp_codec_sync(statep) != DDI_SUCCESS)
1283 		return (0xffff);
1284 
1285 	value = IXP_AUDIO_OUT_PHY_PRIMARY_CODEC |
1286 	    IXP_AUDIO_OUT_PHY_READ |
1287 	    IXP_AUDIO_OUT_PHY_EN |
1288 	    ((unsigned)reg << IXP_AUDIO_OUT_PHY_ADDR_SHIFT);
1289 	PUT32(IXP_AUDIO_OUT_PHY_ADDR_DATA, value);
1290 
1291 	if (audioixp_codec_sync(statep) != DDI_SUCCESS)
1292 		return (0xffff);
1293 
1294 	for (int i = 0; i < 300; i++) {
1295 		result = GET32(IXP_AUDIO_IN_PHY_ADDR_DATA);
1296 		if (result & IXP_AUDIO_IN_PHY_READY)	{
1297 			return (result >> IXP_AUDIO_IN_PHY_DATA_SHIFT);
1298 		}
1299 		drv_usecwait(10);
1300 	}
1301 
1302 done:
1303 	audio_dev_warn(statep->adev, "time out reading codec reg %d", reg);
1304 	return (0xffff);
1305 }
1306 
1307 /*
1308  * audioixp_wr97()
1309  *
1310  * Description:
1311  *	Set the specific AC97 Codec register.
1312  *
1313  * Arguments:
1314  *	void		*arg		The device's state structure
1315  *	uint8_t		reg		AC97 register number
1316  *	uint16_t	data		The data want to be set
1317  */
1318 static void
1319 audioixp_wr97(void *arg, uint8_t reg, uint16_t data)
1320 {
1321 	audioixp_state_t	*statep = arg;
1322 	uint32_t		value;
1323 
1324 	if (audioixp_codec_sync(statep) != DDI_SUCCESS) {
1325 		return;
1326 	}
1327 
1328 	value = IXP_AUDIO_OUT_PHY_PRIMARY_CODEC |
1329 	    IXP_AUDIO_OUT_PHY_WRITE |
1330 	    IXP_AUDIO_OUT_PHY_EN |
1331 	    ((unsigned)reg << IXP_AUDIO_OUT_PHY_ADDR_SHIFT) |
1332 	    ((unsigned)data << IXP_AUDIO_OUT_PHY_DATA_SHIFT);
1333 	PUT32(IXP_AUDIO_OUT_PHY_ADDR_DATA, value);
1334 
1335 	(void) audioixp_rd97(statep, reg);
1336 }
1337 
1338 /*
1339  * audioixp_reset_ac97()
1340  *
1341  * Description:
1342  *	Reset AC97 Codec register.
1343  *
1344  * Arguments:
1345  *	audioixp_state_t	*state		The device's state structure
1346  *
1347  * Returns:
1348  *	DDI_SUCCESS		Reset the codec successfully
1349  *	DDI_FAILURE		Failed to reset the codec
1350  */
1351 static int
1352 audioixp_reset_ac97(audioixp_state_t *statep)
1353 {
1354 	uint32_t	cmd;
1355 	int i;
1356 
1357 	CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_POWER_DOWN);
1358 	drv_usecwait(10);
1359 
1360 	/* register reset */
1361 	SET32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_AC_SOFT_RESET);
1362 	/* force a read to flush caches */
1363 	(void) GET32(IXP_AUDIO_CMD);
1364 
1365 	drv_usecwait(10);
1366 	CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_AC_SOFT_RESET);
1367 
1368 	/* cold reset */
1369 	for (i = 0; i < 300; i++) {
1370 		cmd = GET32(IXP_AUDIO_CMD);
1371 		if (cmd & IXP_AUDIO_CMD_AC_ACTIVE) {
1372 			cmd |= IXP_AUDIO_CMD_AC_RESET | IXP_AUDIO_CMD_AC_SYNC;
1373 			PUT32(IXP_AUDIO_CMD, cmd);
1374 			return (DDI_SUCCESS);
1375 		}
1376 		cmd &= ~IXP_AUDIO_CMD_AC_RESET;
1377 		cmd |= IXP_AUDIO_CMD_AC_SYNC;
1378 		PUT32(IXP_AUDIO_CMD, cmd);
1379 		(void) GET32(IXP_AUDIO_CMD);
1380 		drv_usecwait(10);
1381 		cmd |= IXP_AUDIO_CMD_AC_RESET;
1382 		PUT32(IXP_AUDIO_CMD, cmd);
1383 		drv_usecwait(10);
1384 	}
1385 
1386 	audio_dev_warn(statep->adev, "AC'97 reset timed out");
1387 	return (DDI_FAILURE);
1388 }
1389 
1390 /*
1391  * audioixp_chip_init()
1392  *
1393  * Description:
1394  *	This routine initializes ATI IXP audio controller and the AC97
1395  *	codec.
1396  *
1397  * Arguments:
1398  *	audioixp_state_t	*state		The device's state structure
1399  *
1400  * Returns:
1401  *	DDI_SUCCESS	The hardware was initialized properly
1402  *	DDI_FAILURE	The hardware couldn't be initialized properly
1403  */
1404 static int
1405 audioixp_chip_init(audioixp_state_t *statep)
1406 {
1407 	/*
1408 	 * put the audio controller into quiet state, everything off
1409 	 */
1410 	CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT_DMA);
1411 	CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN_DMA);
1412 
1413 	/* AC97 reset */
1414 	if (audioixp_reset_ac97(statep) != DDI_SUCCESS) {
1415 		audio_dev_warn(statep->adev, "AC97 codec reset failed");
1416 		return (DDI_FAILURE);
1417 	}
1418 
1419 	if (audioixp_codec_ready(statep) != DDI_SUCCESS) {
1420 		audio_dev_warn(statep->adev, "AC97 codec not ready");
1421 		return (DDI_FAILURE);
1422 	}
1423 
1424 	/* enable interrupts */
1425 	PUT32(IXP_AUDIO_INT, 0xffffffff);
1426 	PUT32(
1427 	    IXP_AUDIO_INT_EN,
1428 	    IXP_AUDIO_INT_EN_IN_DMA_OVERFLOW |
1429 	    IXP_AUDIO_INT_EN_STATUS |
1430 	    IXP_AUDIO_INT_EN_OUT_DMA_UNDERFLOW);
1431 	return (DDI_SUCCESS);
1432 
1433 }	/* audioixp_chip_init() */
1434 
1435 /*
1436  * audioixp_attach()
1437  *
1438  * Description:
1439  *	Attach an instance of the audioixp driver. This routine does
1440  * 	the device dependent attach tasks.
1441  *
1442  * Arguments:
1443  *	dev_info_t	*dip	Pointer to the device's dev_info struct
1444  *	ddi_attach_cmd_t cmd	Attach command
1445  *
1446  * Returns:
1447  *	DDI_SUCCESS		The driver was initialized properly
1448  *	DDI_FAILURE		The driver couldn't be initialized properly
1449  */
1450 static int
1451 audioixp_attach(dev_info_t *dip)
1452 {
1453 	uint16_t		cmdeg;
1454 	audioixp_state_t	*statep;
1455 	audio_dev_t		*adev;
1456 	uint32_t		devid;
1457 	const char		*name;
1458 	const char		*rev;
1459 
1460 	/* we don't support high level interrupts in the driver */
1461 	if (ddi_intr_hilevel(dip, 0) != 0) {
1462 		cmn_err(CE_WARN,
1463 		    "!%s%d: unsupported high level interrupt",
1464 		    ddi_driver_name(dip), ddi_get_instance(dip));
1465 		return (DDI_FAILURE);
1466 	}
1467 
1468 	/* allocate the soft state structure */
1469 	statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
1470 	statep->dip = dip;
1471 	ddi_set_driver_private(dip, statep);
1472 
1473 	if (ddi_get_iblock_cookie(dip, 0, &statep->iblock) != DDI_SUCCESS) {
1474 		cmn_err(CE_WARN,
1475 		    "!%s%d: cannot get iblock cookie",
1476 		    ddi_driver_name(dip), ddi_get_instance(dip));
1477 		kmem_free(statep, sizeof (*statep));
1478 		return (DDI_FAILURE);
1479 	}
1480 	mutex_init(&statep->inst_lock, NULL, MUTEX_DRIVER, statep->iblock);
1481 
1482 	/* allocate framework audio device */
1483 	if ((adev = audio_dev_alloc(dip, 0)) == NULL) {
1484 		cmn_err(CE_WARN, "!%s%d: unable to allocate audio dev",
1485 		    ddi_driver_name(dip), ddi_get_instance(dip));
1486 		goto error;
1487 	}
1488 	statep->adev = adev;
1489 
1490 	/* map in the registers */
1491 	if (audioixp_map_regs(statep) != DDI_SUCCESS) {
1492 		audio_dev_warn(adev, "couldn't map registers");
1493 		goto error;
1494 	}
1495 
1496 	/* set device information -- this could be smarter */
1497 	devid = ((pci_config_get16(statep->pcih, PCI_CONF_VENID)) << 16) |
1498 	    pci_config_get16(statep->pcih, PCI_CONF_DEVID);
1499 
1500 	name = "ATI AC'97";
1501 	switch (devid) {
1502 	case IXP_PCI_ID_200:
1503 		rev = "IXP150";
1504 		break;
1505 	case IXP_PCI_ID_300:
1506 		rev = "SB300";
1507 		break;
1508 	case IXP_PCI_ID_400:
1509 		if (pci_config_get8(statep->pcih, PCI_CONF_REVID) & 0x80) {
1510 			rev = "SB450";
1511 		} else {
1512 			rev = "SB400";
1513 		}
1514 		break;
1515 	case IXP_PCI_ID_SB600:
1516 		rev = "SB600";
1517 		break;
1518 	default:
1519 		rev = "Unknown";
1520 		break;
1521 	}
1522 	audio_dev_set_description(adev, name);
1523 	audio_dev_set_version(adev, rev);
1524 
1525 	/* allocate port structures */
1526 	if ((audioixp_alloc_port(statep, IXP_PLAY) != DDI_SUCCESS) ||
1527 	    (audioixp_alloc_port(statep, IXP_REC) != DDI_SUCCESS)) {
1528 		goto error;
1529 	}
1530 
1531 	statep->ac97 = ac97_alloc(dip, audioixp_rd97, audioixp_wr97, statep);
1532 	if (statep->ac97 == NULL) {
1533 		audio_dev_warn(adev, "failed to allocate ac97 handle");
1534 		goto error;
1535 	}
1536 
1537 	/* set PCI command register */
1538 	cmdeg = pci_config_get16(statep->pcih, PCI_CONF_COMM);
1539 	pci_config_put16(statep->pcih, PCI_CONF_COMM,
1540 	    cmdeg | PCI_COMM_IO | PCI_COMM_MAE);
1541 
1542 	/* set up kernel statistics */
1543 	if ((statep->ksp = kstat_create(IXP_NAME, ddi_get_instance(dip),
1544 	    IXP_NAME, "controller", KSTAT_TYPE_INTR, 1,
1545 	    KSTAT_FLAG_PERSISTENT)) != NULL) {
1546 		kstat_install(statep->ksp);
1547 	}
1548 
1549 
1550 	if (audioixp_chip_init(statep) != DDI_SUCCESS) {
1551 		audio_dev_warn(statep->adev, "failed to init chip");
1552 		goto error;
1553 	}
1554 
1555 	/* initialize the AC'97 part */
1556 	if (ac97_init(statep->ac97, adev) != DDI_SUCCESS) {
1557 		audio_dev_warn(adev, "ac'97 initialization failed");
1558 		goto error;
1559 	}
1560 
1561 	/* set up the interrupt handler */
1562 	if (ddi_add_intr(dip, 0, &statep->iblock, NULL, audioixp_intr,
1563 	    (caddr_t)statep) != DDI_SUCCESS) {
1564 		audio_dev_warn(adev, "bad interrupt specification");
1565 	}
1566 	statep->intr_added = B_TRUE;
1567 
1568 	if (audio_dev_register(adev) != DDI_SUCCESS) {
1569 		audio_dev_warn(adev, "unable to register with framework");
1570 		goto error;
1571 	}
1572 
1573 	ddi_report_dev(dip);
1574 
1575 	return (DDI_SUCCESS);
1576 
1577 error:
1578 	audioixp_destroy(statep);
1579 	return (DDI_FAILURE);
1580 }
1581 
1582 /*
1583  * audioixp_detach()
1584  *
1585  * Description:
1586  *	Detach an instance of the audioixp driver.
1587  *
1588  * Arguments:
1589  *	dev_info_t	*dip	Pointer to the device's dev_info struct
1590  *
1591  * Returns:
1592  *	DDI_SUCCESS	The driver was detached
1593  *	DDI_FAILURE	The driver couldn't be detached
1594  */
1595 static int
1596 audioixp_detach(dev_info_t *dip)
1597 {
1598 	audioixp_state_t	*statep;
1599 
1600 	statep = ddi_get_driver_private(dip);
1601 
1602 	if (audio_dev_unregister(statep->adev) != DDI_SUCCESS) {
1603 		return (DDI_FAILURE);
1604 	}
1605 
1606 	audioixp_destroy(statep);
1607 	return (DDI_SUCCESS);
1608 }
1609 
1610 /*
1611  * audioixp_destroy()
1612  *
1613  * Description:
1614  *	This routine releases all resources held by the device instance,
1615  *	as part of either detach or a failure in attach.
1616  *
1617  * Arguments:
1618  *	audioixp_state_t	*state	The device soft state.
1619  */
1620 void
1621 audioixp_destroy(audioixp_state_t *statep)
1622 {
1623 	if (!statep->suspended) {
1624 		PUT32(IXP_AUDIO_INT, GET32(IXP_AUDIO_INT));
1625 		PUT32(IXP_AUDIO_INT_EN, 0);
1626 
1627 		/*
1628 		 * put the audio controller into quiet state, everything off
1629 		 */
1630 		CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT_DMA);
1631 		CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN_DMA);
1632 	}
1633 
1634 	if (statep->intr_added) {
1635 		ddi_remove_intr(statep->dip, 0, statep->iblock);
1636 	}
1637 	if (statep->ksp) {
1638 		kstat_delete(statep->ksp);
1639 	}
1640 
1641 	audioixp_free_port(statep->play_port);
1642 	audioixp_free_port(statep->rec_port);
1643 
1644 	audioixp_unmap_regs(statep);
1645 
1646 	if (statep->ac97) {
1647 		ac97_free(statep->ac97);
1648 	}
1649 
1650 	if (statep->adev) {
1651 		audio_dev_free(statep->adev);
1652 	}
1653 
1654 	mutex_destroy(&statep->inst_lock);
1655 	kmem_free(statep, sizeof (*statep));
1656 }
1657