usr/src/uts/common/io/audio/impl/audio_client.c
changeset 11936 54dc8a89ba0d
parent 11213 497b84226e09
child 12165 e481916a5729
equal deleted inserted replaced
11935:538c866aaac6 11936:54dc8a89ba0d
    19  * CDDL HEADER END
    19  * CDDL HEADER END
    20  */
    20  */
    21 /*
    21 /*
    22  * Copyright (C) 4Front Technologies 1996-2008.
    22  * Copyright (C) 4Front Technologies 1996-2008.
    23  *
    23  *
    24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
    24  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
    25  * Use is subject to license terms.
    25  * Use is subject to license terms.
    26  */
    26  */
    27 
    27 
    28 #include <sys/types.h>
    28 #include <sys/types.h>
    29 #include <sys/sysmacros.h>
    29 #include <sys/sysmacros.h>
   107 auclnt_get_rate(audio_stream_t *sp)
   107 auclnt_get_rate(audio_stream_t *sp)
   108 {
   108 {
   109 	return (sp->s_user_parms->p_rate);
   109 	return (sp->s_user_parms->p_rate);
   110 }
   110 }
   111 
   111 
   112 unsigned
   112 uint_t
   113 auclnt_get_fragsz(audio_stream_t *sp)
   113 auclnt_get_fragsz(audio_stream_t *sp)
   114 {
   114 {
   115 	return (sp->s_fragbytes);
   115 	return (sp->s_fragbytes);
   116 }
   116 }
   117 
   117 
   118 unsigned
   118 uint_t
   119 auclnt_get_framesz(audio_stream_t *sp)
   119 auclnt_get_framesz(audio_stream_t *sp)
   120 {
   120 {
   121 	return (sp->s_framesz);
   121 	return (sp->s_framesz);
   122 }
   122 }
   123 
   123 
   124 unsigned
   124 uint_t
   125 auclnt_get_nfrags(audio_stream_t *sp)
   125 auclnt_get_nfrags(audio_stream_t *sp)
   126 {
   126 {
   127 	return (sp->s_nfrags);
   127 	return (sp->s_nfrags);
   128 }
   128 }
   129 
   129 
   130 unsigned
   130 uint_t
   131 auclnt_get_nframes(audio_stream_t *sp)
   131 auclnt_get_nframes(audio_stream_t *sp)
   132 {
   132 {
   133 	return (sp->s_nframes);
   133 	return (sp->s_nframes);
   134 }
   134 }
   135 
   135 
   136 void
   136 void
   137 auclnt_set_latency(audio_stream_t *sp, unsigned frags, unsigned bytes)
   137 auclnt_set_latency(audio_stream_t *sp, uint_t frags, uint_t bytes)
   138 {
   138 {
   139 	mutex_enter(&sp->s_lock);
   139 	mutex_enter(&sp->s_lock);
   140 	sp->s_hintfrags = (uint16_t)frags;
   140 	sp->s_hintfrags = (uint16_t)frags;
   141 	sp->s_hintsz = bytes;
   141 	sp->s_hintsz = bytes;
   142 	mutex_exit(&sp->s_lock);
   142 	mutex_exit(&sp->s_lock);
   152 auclnt_get_tail(audio_stream_t *sp)
   152 auclnt_get_tail(audio_stream_t *sp)
   153 {
   153 {
   154 	return (sp->s_tail);
   154 	return (sp->s_tail);
   155 }
   155 }
   156 
   156 
   157 unsigned
   157 uint_t
   158 auclnt_get_hidx(audio_stream_t *sp)
   158 auclnt_get_hidx(audio_stream_t *sp)
   159 {
   159 {
   160 	return (sp->s_hidx);
   160 	return (sp->s_hidx);
   161 }
   161 }
   162 
   162 
   163 unsigned
   163 uint_t
   164 auclnt_get_tidx(audio_stream_t *sp)
   164 auclnt_get_tidx(audio_stream_t *sp)
   165 {
   165 {
   166 	return (sp->s_tidx);
   166 	return (sp->s_tidx);
   167 }
   167 }
   168 
   168 
   176 auclnt_output_stream(audio_client_t *c)
   176 auclnt_output_stream(audio_client_t *c)
   177 {
   177 {
   178 	return (&c->c_ostream);
   178 	return (&c->c_ostream);
   179 }
   179 }
   180 
   180 
   181 unsigned
   181 uint_t
   182 auclnt_get_count(audio_stream_t *sp)
   182 auclnt_get_count(audio_stream_t *sp)
   183 {
   183 {
   184 	unsigned	count;
   184 	uint_t	count;
   185 
   185 
   186 	mutex_enter(&sp->s_lock);
   186 	mutex_enter(&sp->s_lock);
   187 	ASSERT((sp->s_head - sp->s_tail) <= sp->s_nframes);
   187 	ASSERT((sp->s_head - sp->s_tail) <= sp->s_nframes);
   188 	count = (unsigned)(sp->s_head - sp->s_tail);
   188 	count = (uint_t)(sp->s_head - sp->s_tail);
   189 	mutex_exit(&sp->s_lock);
   189 	mutex_exit(&sp->s_lock);
   190 
   190 
   191 	return (count);
   191 	return (count);
   192 }
   192 }
   193 
   193 
   194 unsigned
   194 uint_t
   195 auclnt_consume(audio_stream_t *sp, unsigned n)
   195 auclnt_consume(audio_stream_t *sp, uint_t n)
   196 {
   196 {
   197 	mutex_enter(&sp->s_lock);
   197 	mutex_enter(&sp->s_lock);
   198 
   198 
   199 	ASSERT(sp == &sp->s_client->c_istream);
   199 	ASSERT(sp == &sp->s_client->c_istream);
   200 	n = max(n, sp->s_head - sp->s_tail);
   200 	n = max(n, sp->s_head - sp->s_tail);
   210 	mutex_exit(&sp->s_lock);
   210 	mutex_exit(&sp->s_lock);
   211 
   211 
   212 	return (n);
   212 	return (n);
   213 }
   213 }
   214 
   214 
   215 unsigned
   215 uint_t
   216 auclnt_consume_data(audio_stream_t *sp, caddr_t dst, unsigned n)
   216 auclnt_consume_data(audio_stream_t *sp, caddr_t dst, uint_t n)
   217 {
   217 {
   218 	unsigned nframes;
   218 	uint_t nframes;
   219 	unsigned framesz;
   219 	uint_t framesz;
   220 	unsigned cnt;
   220 	uint_t cnt;
   221 	caddr_t	data;
   221 	caddr_t	data;
   222 
   222 
   223 	mutex_enter(&sp->s_lock);
   223 	mutex_enter(&sp->s_lock);
   224 
   224 
   225 	nframes = sp->s_nframes;
   225 	nframes = sp->s_nframes;
   231 	ASSERT(sp->s_hidx < nframes);
   231 	ASSERT(sp->s_hidx < nframes);
   232 
   232 
   233 	cnt = n = min(n, sp->s_head - sp->s_tail);
   233 	cnt = n = min(n, sp->s_head - sp->s_tail);
   234 	data = sp->s_data + (sp->s_tidx * framesz);
   234 	data = sp->s_data + (sp->s_tidx * framesz);
   235 	do {
   235 	do {
   236 		unsigned nf, nb;
   236 		uint_t nf, nb;
   237 
   237 
   238 		nf = min(nframes - sp->s_tidx, n);
   238 		nf = min(nframes - sp->s_tidx, n);
   239 		nb = nf * framesz;
   239 		nb = nf * framesz;
   240 
   240 
   241 		bcopy(data, dst, nb);
   241 		bcopy(data, dst, nb);
   257 	mutex_exit(&sp->s_lock);
   257 	mutex_exit(&sp->s_lock);
   258 
   258 
   259 	return (cnt);
   259 	return (cnt);
   260 }
   260 }
   261 
   261 
   262 unsigned
   262 uint_t
   263 auclnt_produce(audio_stream_t *sp, unsigned n)
   263 auclnt_produce(audio_stream_t *sp, uint_t n)
   264 {
   264 {
   265 	mutex_enter(&sp->s_lock);
   265 	mutex_enter(&sp->s_lock);
   266 
   266 
   267 	ASSERT(sp == &sp->s_client->c_ostream);
   267 	ASSERT(sp == &sp->s_client->c_ostream);
   268 	n = max(n, sp->s_nframes - (sp->s_head - sp->s_tail));
   268 	n = max(n, sp->s_nframes - (sp->s_head - sp->s_tail));
   278 	mutex_exit(&sp->s_lock);
   278 	mutex_exit(&sp->s_lock);
   279 
   279 
   280 	return (n);
   280 	return (n);
   281 }
   281 }
   282 
   282 
   283 unsigned
   283 uint_t
   284 auclnt_produce_data(audio_stream_t *sp, caddr_t src, unsigned n)
   284 auclnt_produce_data(audio_stream_t *sp, caddr_t src, uint_t n)
   285 {
   285 {
   286 	unsigned nframes;
   286 	uint_t nframes;
   287 	unsigned framesz;
   287 	uint_t framesz;
   288 	unsigned cnt;
   288 	uint_t cnt;
   289 	caddr_t data;
   289 	caddr_t data;
   290 
   290 
   291 	mutex_enter(&sp->s_lock);
   291 	mutex_enter(&sp->s_lock);
   292 
   292 
   293 	nframes = sp->s_nframes;
   293 	nframes = sp->s_nframes;
   299 	ASSERT(sp->s_hidx < nframes);
   299 	ASSERT(sp->s_hidx < nframes);
   300 
   300 
   301 	cnt = n = min(n, nframes - (sp->s_head - sp->s_tail));
   301 	cnt = n = min(n, nframes - (sp->s_head - sp->s_tail));
   302 	data = sp->s_data + (sp->s_hidx * framesz);
   302 	data = sp->s_data + (sp->s_hidx * framesz);
   303 	do {
   303 	do {
   304 		unsigned nf, nb;
   304 		uint_t nf, nb;
   305 
   305 
   306 		nf = min(nframes - sp->s_hidx, n);
   306 		nf = min(nframes - sp->s_hidx, n);
   307 		nb = nf * framesz;
   307 		nb = nf * framesz;
   308 
   308 
   309 		bcopy(src, data, nb);
   309 		bcopy(src, data, nb);
   330 
   330 
   331 int
   331 int
   332 auclnt_read(audio_client_t *c, struct uio *uio)
   332 auclnt_read(audio_client_t *c, struct uio *uio)
   333 {
   333 {
   334 	audio_stream_t	*sp = &c->c_istream;
   334 	audio_stream_t	*sp = &c->c_istream;
   335 	unsigned	cnt;
   335 	uint_t		cnt;
   336 	int		rv = 0;
   336 	int		rv = 0;
   337 	offset_t	loff;
   337 	offset_t	loff;
   338 	int		eagain;
   338 	int		eagain;
       
   339 	uint_t		tidx;
       
   340 	uint_t		framesz;
   339 
   341 
   340 	loff = uio->uio_loffset;
   342 	loff = uio->uio_loffset;
   341 	eagain = EAGAIN;
   343 	eagain = EAGAIN;
   342 
   344 
   343 	mutex_enter(&sp->s_lock);
   345 	mutex_enter(&sp->s_lock);
   346 		mutex_exit(&sp->s_lock);
   348 		mutex_exit(&sp->s_lock);
   347 		auclnt_start(sp);
   349 		auclnt_start(sp);
   348 		mutex_enter(&sp->s_lock);
   350 		mutex_enter(&sp->s_lock);
   349 	}
   351 	}
   350 
   352 
       
   353 
       
   354 	framesz = sp->s_framesz;
       
   355 
   351 	ASSERT(sp->s_head >= sp->s_tail);
   356 	ASSERT(sp->s_head >= sp->s_tail);
   352 	ASSERT(sp->s_tidx < sp->s_nframes);
   357 	ASSERT(sp->s_tidx < sp->s_nframes);
   353 	ASSERT(sp->s_hidx < sp->s_nframes);
   358 
   354 
   359 	while (uio->uio_resid >= framesz) {
   355 	while (uio->uio_resid >= sp->s_framesz) {
       
   356 
   360 
   357 		while ((cnt = (sp->s_head - sp->s_tail)) == 0) {
   361 		while ((cnt = (sp->s_head - sp->s_tail)) == 0) {
   358 			if (uio->uio_fmode & (FNONBLOCK|FNDELAY)) {
   362 			if (uio->uio_fmode & (FNONBLOCK|FNDELAY)) {
   359 				mutex_exit(&sp->s_lock);
   363 				mutex_exit(&sp->s_lock);
   360 				return (eagain);
   364 				return (eagain);
   363 				mutex_exit(&sp->s_lock);
   367 				mutex_exit(&sp->s_lock);
   364 				return (EINTR);
   368 				return (EINTR);
   365 			}
   369 			}
   366 		}
   370 		}
   367 
   371 
   368 		cnt = min(cnt, sp->s_nframes - sp->s_tidx);
   372 		tidx = sp->s_tidx;
   369 		cnt = min(cnt, (uio->uio_resid / sp->s_framesz));
   373 		cnt = min(cnt, sp->s_nframes - tidx);
   370 
   374 		cnt = min(cnt, (uio->uio_resid / framesz));
   371 		rv = uiomove(sp->s_data + (sp->s_tidx * sp->s_framesz),
   375 
   372 		    cnt * sp->s_framesz, UIO_READ, uio);
   376 		mutex_exit(&sp->s_lock);
       
   377 		rv = uiomove(sp->s_data + (tidx * framesz),
       
   378 		    cnt * framesz, UIO_READ, uio);
       
   379 
   373 		uio->uio_loffset = loff;
   380 		uio->uio_loffset = loff;
   374 		eagain = 0;
   381 		eagain = 0;
   375 
   382 
   376 		if (rv != 0) {
   383 		if (rv != 0) {
   377 			mutex_exit(&sp->s_lock);
       
   378 			return (rv);
   384 			return (rv);
   379 		}
   385 		}
   380 
   386 
       
   387 		mutex_enter(&sp->s_lock);
   381 		sp->s_tail += cnt;
   388 		sp->s_tail += cnt;
   382 		sp->s_tidx += cnt;
   389 		sp->s_tidx += cnt;
   383 		if (sp->s_tidx == sp->s_nframes) {
   390 		if (sp->s_tidx == sp->s_nframes) {
   384 			sp->s_tidx = 0;
   391 			sp->s_tidx = 0;
   385 		}
   392 		}
   398 
   405 
   399 int
   406 int
   400 auclnt_write(audio_client_t *c, struct uio *uio)
   407 auclnt_write(audio_client_t *c, struct uio *uio)
   401 {
   408 {
   402 	audio_stream_t *sp = &c->c_ostream;
   409 	audio_stream_t *sp = &c->c_ostream;
   403 	unsigned	cnt;
   410 	uint_t		cnt;
   404 	int		rv = 0;
   411 	int		rv = 0;
   405 	offset_t	loff;
   412 	offset_t	loff;
   406 	int		eagain;
   413 	int		eagain;
       
   414 	uint_t		framesz;
       
   415 	uint_t		hidx;
   407 
   416 
   408 	loff = uio->uio_loffset;
   417 	loff = uio->uio_loffset;
   409 	eagain = EAGAIN;
   418 	eagain = EAGAIN;
   410 
   419 
   411 	mutex_enter(&sp->s_lock);
   420 	mutex_enter(&sp->s_lock);
   412 
   421 
       
   422 	framesz = sp->s_framesz;
       
   423 
   413 	ASSERT(sp->s_head >= sp->s_tail);
   424 	ASSERT(sp->s_head >= sp->s_tail);
   414 	ASSERT(sp->s_tidx < sp->s_nframes);
       
   415 	ASSERT(sp->s_hidx < sp->s_nframes);
   425 	ASSERT(sp->s_hidx < sp->s_nframes);
   416 
   426 
   417 	while (uio->uio_resid >= sp->s_framesz) {
   427 	while (uio->uio_resid >= framesz) {
   418 
   428 
   419 		while ((cnt = sp->s_nframes - (sp->s_head - sp->s_tail)) == 0) {
   429 		while ((cnt = sp->s_nframes - (sp->s_head - sp->s_tail)) == 0) {
   420 			if (uio->uio_fmode & (FNONBLOCK|FNDELAY)) {
   430 			if (uio->uio_fmode & (FNONBLOCK|FNDELAY)) {
   421 				mutex_exit(&sp->s_lock);
   431 				mutex_exit(&sp->s_lock);
   422 				return (eagain);
   432 				return (eagain);
   425 				mutex_exit(&sp->s_lock);
   435 				mutex_exit(&sp->s_lock);
   426 				return (EINTR);
   436 				return (EINTR);
   427 			}
   437 			}
   428 		}
   438 		}
   429 
   439 
   430 		cnt = min(cnt, sp->s_nframes - sp->s_hidx);
   440 		hidx = sp->s_hidx;
   431 		cnt = min(cnt, (uio->uio_resid / sp->s_framesz));
   441 		cnt = min(cnt, sp->s_nframes - hidx);
   432 
   442 		cnt = min(cnt, (uio->uio_resid / framesz));
   433 		rv = uiomove(sp->s_data + (sp->s_hidx * sp->s_framesz),
   443 
   434 		    cnt * sp->s_framesz, UIO_WRITE, uio);
   444 		/*
       
   445 		 * We have to drop the stream lock, because the
       
   446 		 * uiomove might require doing a page in, which could
       
   447 		 * get blocked behind the PIL of the audio processing
       
   448 		 * thread which also grabs the s_lock.  (Hence, there
       
   449 		 * is a risk of deadlock due to priority inversion.)
       
   450 		 */
       
   451 		mutex_exit(&sp->s_lock);
       
   452 
       
   453 		rv = uiomove(sp->s_data + (hidx * framesz),
       
   454 		    cnt * framesz, UIO_WRITE, uio);
       
   455 
   435 		uio->uio_loffset = loff;
   456 		uio->uio_loffset = loff;
   436 		eagain = 0;
   457 		eagain = 0;
   437 
   458 
   438 		if (rv != 0) {
   459 		if (rv != 0) {
   439 			mutex_exit(&sp->s_lock);
       
   440 			return (rv);
   460 			return (rv);
   441 		}
   461 		}
       
   462 
       
   463 		mutex_enter(&sp->s_lock);
   442 
   464 
   443 		sp->s_head += cnt;
   465 		sp->s_head += cnt;
   444 		sp->s_hidx += cnt;
   466 		sp->s_hidx += cnt;
   445 		if (sp->s_hidx == sp->s_nframes) {
   467 		if (sp->s_hidx == sp->s_nframes) {
   446 			sp->s_hidx = 0;
   468 			sp->s_hidx = 0;
   507 {
   529 {
   508 	pollwakeup(&c->c_pollhead, events);
   530 	pollwakeup(&c->c_pollhead, events);
   509 }
   531 }
   510 
   532 
   511 void
   533 void
   512 auclnt_get_output_qlen(audio_client_t *c, unsigned *slen, unsigned *flen)
   534 auclnt_get_output_qlen(audio_client_t *c, uint_t *slen, uint_t *flen)
   513 {
   535 {
   514 	audio_stream_t	*sp = &c->c_ostream;
   536 	audio_stream_t	*sp = &c->c_ostream;
   515 	audio_engine_t	*e = sp->s_engine;
   537 	audio_engine_t	*e = sp->s_engine;
   516 	uint64_t	el, sl;
   538 	uint64_t	el, sl;
   517 	unsigned	cnt, er, sr;
   539 	uint_t		cnt, er, sr;
   518 
   540 
   519 	if (e == NULL) {
   541 	if (e == NULL) {
   520 		/* if no output engine, can't do it! */
   542 		/* if no output engine, can't do it! */
   521 		*slen = 0;
   543 		*slen = 0;
   522 		*flen = 0;
   544 		*flen = 0;
   531 		el = (e->e_head - e->e_tail);
   553 		el = (e->e_head - e->e_tail);
   532 	}
   554 	}
   533 	er = e->e_rate;
   555 	er = e->e_rate;
   534 	sl = sp->s_cnv_cnt;
   556 	sl = sp->s_cnv_cnt;
   535 	sr = sp->s_user_parms->p_rate;
   557 	sr = sp->s_user_parms->p_rate;
   536 	cnt = (unsigned)(sp->s_head - sp->s_tail);
   558 	cnt = (uint_t)(sp->s_head - sp->s_tail);
   537 	mutex_exit(&sp->s_lock);
   559 	mutex_exit(&sp->s_lock);
   538 	mutex_exit(&e->e_lock);
   560 	mutex_exit(&e->e_lock);
   539 
   561 
   540 	/* engine frames converted to stream rate, plus stream frames */
   562 	/* engine frames converted to stream rate, plus stream frames */
   541 	*slen = cnt;
   563 	*slen = cnt;
   542 	*flen = ((unsigned)(((el * sr) / er) + sl));
   564 	*flen = ((uint_t)(((el * sr) / er) + sl));
   543 }
   565 }
   544 
   566 
   545 int
   567 int
   546 auclnt_set_format(audio_stream_t *sp, int fmt)
   568 auclnt_set_format(audio_stream_t *sp, int fmt)
   547 {
   569 {
  1195 	}
  1217 	}
  1196 	rw_exit(&auimpl_client_lock);
  1218 	rw_exit(&auimpl_client_lock);
  1197 	return (c);
  1219 	return (c);
  1198 }
  1220 }
  1199 
  1221 
       
  1222 int
       
  1223 auclnt_serialize(audio_client_t *c)
       
  1224 {
       
  1225 	mutex_enter(&c->c_lock);
       
  1226 	while (c->c_serialize) {
       
  1227 		if (cv_wait_sig(&c->c_cv, &c->c_lock) == 0) {
       
  1228 			mutex_exit(&c->c_lock);
       
  1229 			return (EINTR);
       
  1230 		}
       
  1231 	}
       
  1232 	c->c_serialize = B_TRUE;
       
  1233 	mutex_exit(&c->c_lock);
       
  1234 	return (0);
       
  1235 }
       
  1236 
       
  1237 void
       
  1238 auclnt_unserialize(audio_client_t *c)
       
  1239 {
       
  1240 	mutex_enter(&c->c_lock);
       
  1241 	ASSERT(c->c_serialize);
       
  1242 	c->c_serialize = B_FALSE;
       
  1243 	cv_broadcast(&c->c_cv);
       
  1244 	mutex_exit(&c->c_lock);
       
  1245 }
       
  1246 
       
  1247 void
       
  1248 auclnt_hold(audio_client_t *c)
       
  1249 {
       
  1250 	mutex_enter(&c->c_lock);
       
  1251 	c->c_refcnt++;
       
  1252 	mutex_exit(&c->c_lock);
       
  1253 }
       
  1254 
  1200 void
  1255 void
  1201 auclnt_release(audio_client_t *c)
  1256 auclnt_release(audio_client_t *c)
  1202 {
  1257 {
  1203 	mutex_enter(&c->c_lock);
  1258 	mutex_enter(&c->c_lock);
  1204 	ASSERT(c->c_refcnt > 0);
  1259 	ASSERT(c->c_refcnt > 0);
  1206 	if (c->c_refcnt == 0)
  1261 	if (c->c_refcnt == 0)
  1207 		cv_broadcast(&c->c_cv);
  1262 		cv_broadcast(&c->c_cv);
  1208 	mutex_exit(&c->c_lock);
  1263 	mutex_exit(&c->c_lock);
  1209 }
  1264 }
  1210 
  1265 
  1211 unsigned
  1266 uint_t
  1212 auclnt_dev_get_serial(audio_dev_t *d)
  1267 auclnt_dev_get_serial(audio_dev_t *d)
  1213 {
  1268 {
  1214 	return (d->d_serial);
  1269 	return (d->d_serial);
  1215 }
  1270 }
  1216 
  1271 
  1238 	rw_exit(&auimpl_client_lock);
  1293 	rw_exit(&auimpl_client_lock);
  1239 }
  1294 }
  1240 
  1295 
  1241 
  1296 
  1242 int
  1297 int
  1243 auclnt_open(audio_client_t *c, unsigned fmts, int oflag)
  1298 auclnt_open(audio_client_t *c, uint_t fmts, int oflag)
  1244 {
  1299 {
  1245 	audio_stream_t	*sp;
  1300 	audio_stream_t	*sp;
  1246 	audio_dev_t	*d = c->c_dev;
  1301 	audio_dev_t	*d = c->c_dev;
  1247 	int		rv = 0;
  1302 	int		rv = 0;
  1248 	int		flags;
  1303 	int		flags;
  1410 auclnt_get_dev_version(audio_dev_t *dev)
  1465 auclnt_get_dev_version(audio_dev_t *dev)
  1411 {
  1466 {
  1412 	return (dev->d_vers);
  1467 	return (dev->d_vers);
  1413 }
  1468 }
  1414 
  1469 
  1415 unsigned
  1470 uint_t
  1416 auclnt_get_dev_capab(audio_dev_t *dev)
  1471 auclnt_get_dev_capab(audio_dev_t *dev)
  1417 {
  1472 {
  1418 	uint32_t	flags;
  1473 	uint32_t	flags;
  1419 	unsigned	caps = 0;
  1474 	uint_t		caps = 0;
  1420 
  1475 
  1421 	flags = dev->d_flags;
  1476 	flags = dev->d_flags;
  1422 
  1477 
  1423 	if (flags & DEV_OUTPUT_CAP)
  1478 	if (flags & DEV_OUTPUT_CAP)
  1424 		caps |= AUDIO_CLIENT_CAP_PLAY;
  1479 		caps |= AUDIO_CLIENT_CAP_PLAY;
  1575     int (*walker)(audio_ctrl_t *, void *),
  1630     int (*walker)(audio_ctrl_t *, void *),
  1576     void *arg)
  1631     void *arg)
  1577 {
  1632 {
  1578 	audio_ctrl_t *ctrl;
  1633 	audio_ctrl_t *ctrl;
  1579 
  1634 
  1580 	rw_enter(&d->d_ctrl_lock, RW_READER);
  1635 	mutex_enter(&d->d_ctrl_lock);
  1581 	for (ctrl = list_head(&d->d_controls); ctrl;
  1636 	for (ctrl = list_head(&d->d_controls); ctrl;
  1582 	    ctrl = list_next(&d->d_controls, ctrl)) {
  1637 	    ctrl = list_next(&d->d_controls, ctrl)) {
  1583 		if (walker(ctrl, arg) == AUDIO_WALK_STOP)
  1638 		if (walker(ctrl, arg) == AUDIO_WALK_STOP)
  1584 			break;
  1639 			break;
  1585 	}
  1640 	}
  1586 	rw_exit(&d->d_ctrl_lock);
  1641 	mutex_exit(&d->d_ctrl_lock);
  1587 }
  1642 }
  1588 
  1643 
  1589 /*
  1644 /*
  1590  * This will search all controls attached to an
  1645  * This will search all controls attached to an
  1591  * audio device for a control with the desired name.
  1646  * audio device for a control with the desired name.
  1602 	audio_ctrl_t *ctrl;
  1657 	audio_ctrl_t *ctrl;
  1603 
  1658 
  1604 	/* Verify argument */
  1659 	/* Verify argument */
  1605 	ASSERT(d);
  1660 	ASSERT(d);
  1606 
  1661 
  1607 	rw_enter(&d->d_ctrl_lock, RW_READER);
  1662 	mutex_enter(&d->d_ctrl_lock);
  1608 	for (ctrl = list_head(&d->d_controls); ctrl;
  1663 	for (ctrl = list_head(&d->d_controls); ctrl;
  1609 	    ctrl = list_next(&d->d_controls, ctrl)) {
  1664 	    ctrl = list_next(&d->d_controls, ctrl)) {
  1610 		if (strcmp(ctrl->ctrl_name, name) == 0) {
  1665 		if (strcmp(ctrl->ctrl_name, name) == 0) {
  1611 			rw_exit(&d->d_ctrl_lock);
  1666 			mutex_exit(&d->d_ctrl_lock);
  1612 			return (ctrl);
  1667 			return (ctrl);
  1613 		}
  1668 		}
  1614 	}
  1669 	}
  1615 	rw_exit(&d->d_ctrl_lock);
  1670 	mutex_exit(&d->d_ctrl_lock);
  1616 	return (NULL);
  1671 	return (NULL);
  1617 }
  1672 }
  1618 
  1673 
  1619 /*
  1674 /*
  1620  * Given a known control, get its attributes.
  1675  * Given a known control, get its attributes.