diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/cmd/devfsadm/i386/lx_link_i386.c | 19 | ||||
| -rw-r--r-- | usr/src/uts/common/Makefile.files | 2 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/io/lx_audio.c | 1996 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/io/lx_audio.conf | 27 | ||||
| -rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_audio.h | 130 | ||||
| -rw-r--r-- | usr/src/uts/intel/Makefile.intel | 2 | ||||
| -rw-r--r-- | usr/src/uts/intel/lx_audio/Makefile | 100 |
7 files changed, 1 insertions, 2275 deletions
diff --git a/usr/src/cmd/devfsadm/i386/lx_link_i386.c b/usr/src/cmd/devfsadm/i386/lx_link_i386.c index 4f8a17b655..b99a8361a0 100644 --- a/usr/src/cmd/devfsadm/i386/lx_link_i386.c +++ b/usr/src/cmd/devfsadm/i386/lx_link_i386.c @@ -29,19 +29,15 @@ #include <strings.h> #include <stdio.h> #include <sys/lx_ptm.h> -#include <sys/lx_audio.h> #include <sys/lx_autofs.h> static int lx_ptm(di_minor_t minor, di_node_t node); -static int lx_audio(di_minor_t minor, di_node_t node); static int lx_autofs(di_minor_t minor, di_node_t node); static int lx_systrace(di_minor_t minor, di_node_t node); static devfsadm_create_t lx_create_cbt[] = { { "pseudo", "ddi_pseudo", LX_PTM_DRV, TYPE_EXACT | DRV_EXACT, ILEVEL_0, lx_ptm }, - { "pseudo", "ddi_pseudo", LX_AUDIO_DRV, - TYPE_EXACT | DRV_EXACT, ILEVEL_0, lx_audio }, { "pseudo", "ddi_pseudo", LX_AUTOFS_NAME, TYPE_EXACT | DRV_EXACT, ILEVEL_0, lx_autofs }, { "pseudo", "ddi_pseudo", "lx_systrace", @@ -62,21 +58,6 @@ lx_ptm(di_minor_t minor, di_node_t node) } static int -lx_audio(di_minor_t minor, di_node_t node) -{ - char *mname = di_minor_name(minor); - - if (strcmp(LXA_MINORNAME_DEVCTL, mname) == 0) - (void) devfsadm_mklink("brand/lx/audio_devctl", node, minor, 0); - if (strcmp(LXA_MINORNAME_DSP, mname) == 0) - (void) devfsadm_mklink("brand/lx/dsp", node, minor, 0); - if (strcmp(LXA_MINORNAME_MIXER, mname) == 0) - (void) devfsadm_mklink("brand/lx/mixer", node, minor, 0); - - return (DEVFSADM_CONTINUE); -} - -static int lx_autofs(di_minor_t minor, di_node_t node) { char *mname = di_minor_name(minor); diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index c27af062e6..cd2eea6072 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -497,8 +497,6 @@ PTM_OBJS += ptm.o LX_PTM_OBJS += lx_ptm.o -LX_AUDIO_OBJS += lx_audio.o - LX_NETLINK_OBJS += lx_netlink.o MII_OBJS += mii.o mii_cicada.o mii_natsemi.o mii_intel.o mii_qualsemi.o \ diff --git a/usr/src/uts/common/brand/lx/io/lx_audio.c b/usr/src/uts/common/brand/lx/io/lx_audio.c deleted file mode 100644 index e8c6234d92..0000000000 --- a/usr/src/uts/common/brand/lx/io/lx_audio.c +++ /dev/null @@ -1,1996 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#include <sys/audio.h> -#include <sys/conf.h> -#include <sys/debug.h> -#include <sys/disp.h> -#include <sys/ddi.h> -#include <sys/file.h> -#include <sys/id_space.h> -#include <sys/kmem.h> -#include <sys/lx_audio.h> -#include <sys/mixer.h> -#include <sys/modhash.h> -#include <sys/stat.h> -#include <sys/sunddi.h> -#include <sys/sunldi.h> -#include <sys/sysmacros.h> -#include <sys/stropts.h> -#include <sys/types.h> -#include <sys/zone.h> - -/* Properties used by the lx_audio driver */ -#define LXA_PROP_INPUTDEV "inputdev" -#define LXA_PROP_OUTPUTDEV "outputdev" - -/* default device paths used by this driver */ -#define LXA_DEV_DEFAULT "/dev/audio" -#define LXA_DEV_CUSTOM_DIR "/dev/sound/" - -/* maximum possible number of concurrent opens of this driver */ -#define LX_AUDIO_MAX_OPENS 1024 - -/* - * these are default fragment size and fragment count values. - * these values were chosen to make quake work well on my - * laptop: 2Ghz Pentium M + NVIDIA GeForce Go 6400. - * - * for reference: - * - 1 sec of stereo output at 44Khz is about 171 Kb of data - * - 1 sec of mono output at 8Khz is about 8Kb of data - */ -#define LXA_OSS_FRAG_SIZE (1024) /* 1/8 sec at 8Khz mono */ -#define LXA_OSS_FRAG_CNT (1024 * 2) - -/* maximum ammount of fragment memory we'll allow a process to mmap */ -#define LXA_OSS_FRAG_MEM (1024 * 1024 * 2) /* 2Mb */ - -/* forward declarations */ -typedef struct lxa_state lxa_state_t; -typedef struct lxa_zstate lxa_zstate_t; - -/* - * Structure and enum declarations - */ -typedef enum { - LXA_TYPE_INVALID = 0, - LXA_TYPE_AUDIO = 1, /* audio device */ - LXA_TYPE_AUDIOCTL = 2 /* audio control/mixer device */ -} lxa_dev_type_t; - -struct lxa_zstate { - char *lxa_zs_zonename; - - /* - * we could store the input/output audio device setting here, - * but instead we're keeing them as device node properties - * so that a user can easily see the audio configuration for - * a zone via prtconf. - */ - - /* - * OSS doesn't support multiple opens of the audio device. - * (multiple opens of the mixer device are supported.) - * so here we'll keep a pointer to any open input/output - * streams. (OSS does support two opens if one is for input - * and the other is for output.) - */ - lxa_state_t *lxa_zs_istate; - lxa_state_t *lxa_zs_ostate; - - /* - * we need to cache channel gain and balance. channel gain and - * balance map to PCM volume in OSS, which are supposedly a property - * of the underlying hardware. but in solaris, channels are - * implemented in software and only exist when an audio device - * is actually open. (each open returns a unique channel.) OSS - * apps will expect consistent PCM volume set/get operations to - * work even if no audio device is open. hence, if no underlying - * device is open we need to cache the gain and balance setting. - */ - lxa_mixer_levels_t lxa_zs_pcm_levels; -}; - -struct lxa_state { - lxa_zstate_t *lxas_zs; /* zone state pointer */ - - dev_t lxas_dev_old; /* dev_t used to open the device */ - dev_t lxas_dev_new; /* new dev_t assigned to an open */ - int lxas_flags; /* original flags passed to open */ - lxa_dev_type_t lxas_type; /* type of device that was opened */ - - int lxas_devs_same; /* input and output device the same? */ - - /* input device variables */ - ldi_handle_t lxas_idev_lh; /* ldi handle for access */ - int lxas_idev_flags; /* flags used for open */ - - /* output device variables */ - ldi_handle_t lxas_odev_lh; /* ldi handle for access */ - int lxas_odev_flags; /* flags used for open */ - - /* - * since we support multiplexing of devices we need to remember - * certain parameters about the devices - */ - uint_t lxas_hw_features; - uint_t lxas_sw_features; - - uint_t lxas_frag_size; - uint_t lxas_frag_cnt; - - /* - * members needed to support mmap device access. note that to - * simplifly things we only support one mmap access per open. - */ - ddi_umem_cookie_t lxas_umem_cookie; - char *lxas_umem_ptr; - size_t lxas_umem_len; - kthread_t *lxas_mmap_thread; - int lxas_mmap_thread_running; - int lxas_mmap_thread_exit; - int lxas_mmap_thread_frag; -}; - -/* - * Global variables - */ -dev_info_t *lxa_dip = NULL; -kmutex_t lxa_lock; -id_space_t *lxa_minor_id = NULL; -mod_hash_t *lxa_state_hash = NULL; -mod_hash_t *lxa_zstate_hash = NULL; -size_t lxa_state_hash_size = 15; -size_t lxa_zstate_hash_size = 15; -size_t lxa_registered_zones = 0; - -/* - * function declarations - */ -static void lxa_mmap_output_disable(lxa_state_t *); - -/* - * functions - */ -static void -lxa_state_close(lxa_state_t *lxa_state) -{ - lxa_zstate_t *lxa_zs = lxa_state->lxas_zs; - minor_t minor = getminor(lxa_state->lxas_dev_new); - - /* disable any mmap output that might still be going on */ - lxa_mmap_output_disable(lxa_state); - - /* - * if this was the active input/output device, unlink it from - * the global zone state so that other opens of the audio device - * can now succeed. - */ - mutex_enter(&lxa_lock); - if (lxa_zs->lxa_zs_istate == lxa_state) - lxa_zs->lxa_zs_istate = NULL; - if (lxa_zs->lxa_zs_ostate == lxa_state) { - lxa_zs->lxa_zs_ostate = NULL; - } - mutex_exit(&lxa_lock); - - /* remove this state structure from the hash (if it's there) */ - (void) mod_hash_remove(lxa_state_hash, - (mod_hash_key_t)(uintptr_t)minor, (mod_hash_val_t *)&lxa_state); - - /* close any audio device that we have open */ - if (lxa_state->lxas_idev_lh != NULL) - (void) ldi_close(lxa_state->lxas_idev_lh, - lxa_state->lxas_idev_flags, kcred); - if (lxa_state->lxas_odev_lh != NULL) - (void) ldi_close(lxa_state->lxas_odev_lh, - lxa_state->lxas_odev_flags, kcred); - - /* free up any memory allocated by mmaps */ - if (lxa_state->lxas_umem_cookie != NULL) - ddi_umem_free(lxa_state->lxas_umem_cookie); - - /* release the id associated with this state structure */ - id_free(lxa_minor_id, minor); - - kmem_free(lxa_state, sizeof (*lxa_state)); -} - -static char * -getzonename(void) -{ - return (curproc->p_zone->zone_name); -} - -static char * -lxa_devprop_name(char *zname, char *pname) -{ - char *zpname; - int n; - - ASSERT((pname != NULL) && (zname != NULL)); - - /* prepend the zone name to the property name */ - n = snprintf(NULL, 0, "%s_%s", zname, pname) + 1; - zpname = kmem_alloc(n, KM_SLEEP); - (void) snprintf(zpname, n, "%s_%s", zname, pname); - - return (zpname); -} - -static int -lxa_devprop_verify(char *pval) -{ - int n; - - ASSERT(pval != NULL); - - if (strcmp(pval, "default") == 0) - return (0); - - /* make sure the value is an integer */ - for (n = 0; pval[n] != '\0'; n++) { - if ((pval[n] < '0') && (pval[n] > '9')) { - return (-1); - } - } - - return (0); -} - -static char * -lxa_devprop_lookup(char *zname, char *pname, lxa_dev_type_t lxa_type) -{ - char *zprop_name, *pval; - char *dev_path; - int n, rv; - - ASSERT((pname != NULL) && (zname != NULL)); - ASSERT((lxa_type == LXA_TYPE_AUDIO) || (lxa_type == LXA_TYPE_AUDIOCTL)); - - zprop_name = lxa_devprop_name(zname, pname); - - /* attempt to lookup the property */ - rv = ddi_prop_lookup_string(DDI_DEV_T_ANY, lxa_dip, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, zprop_name, &pval); - strfree(zprop_name); - - if (rv != DDI_PROP_SUCCESS) - return (NULL); - - if (lxa_devprop_verify(pval) != 0) { - ddi_prop_free(pval); - return (NULL); - } - - if (strcmp(pval, "none") == 0) { - /* there is no audio device specified */ - return (NULL); - } else if (strcmp(pval, "default") == 0) { - /* use the default audio device on the system */ - dev_path = strdup(LXA_DEV_DEFAULT); - } else { - /* a custom audio device was specified, generate a path */ - n = snprintf(NULL, 0, "%s%s", LXA_DEV_CUSTOM_DIR, pval) + 1; - dev_path = kmem_alloc(n, KM_SLEEP); - (void) snprintf(dev_path, n, "%s%s", LXA_DEV_CUSTOM_DIR, pval); - } - ddi_prop_free(pval); - - /* - * if this is an audio control device so we need to append - * "ctl" to the path - */ - if (lxa_type == LXA_TYPE_AUDIOCTL) { - char *tmp; - n = snprintf(NULL, 0, "%s%s", dev_path, "ctl") + 1; - tmp = kmem_alloc(n, KM_SLEEP); - (void) snprintf(tmp, n, "%s%s", dev_path, "ctl"); - strfree(dev_path); - dev_path = tmp; - } - - return (dev_path); -} - -static int -lxa_dev_getfeatures(lxa_state_t *lxa_state) -{ - audio_info_t ai_idev, ai_odev; - int n, rv; - - /* set a default fragment size */ - lxa_state->lxas_frag_size = LXA_OSS_FRAG_SIZE; - lxa_state->lxas_frag_cnt = LXA_OSS_FRAG_CNT; - - /* get info for the currently open audio devices */ - if ((lxa_state->lxas_idev_lh != NULL) && - ((rv = ldi_ioctl(lxa_state->lxas_idev_lh, - AUDIO_GETINFO, (intptr_t)&ai_idev, FKIOCTL, kcred, &n)) != 0)) - return (rv); - if ((lxa_state->lxas_odev_lh != NULL) && - ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, - AUDIO_GETINFO, (intptr_t)&ai_odev, FKIOCTL, kcred, &n)) != 0)) - return (rv); - - /* if we're only open for reading or writing then it's easy */ - if (lxa_state->lxas_idev_lh == NULL) { - lxa_state->lxas_sw_features = ai_odev.sw_features; - lxa_state->lxas_hw_features = ai_odev.hw_features; - return (0); - } else if (lxa_state->lxas_odev_lh == NULL) { - lxa_state->lxas_sw_features = ai_idev.sw_features; - lxa_state->lxas_hw_features = ai_idev.hw_features; - return (0); - } - - /* - * well if we're open for reading and writing but the underlying - * device is the same then it's also pretty easy - */ - if (lxa_state->lxas_devs_same) { - if ((ai_odev.sw_features != ai_idev.sw_features) || - (ai_odev.hw_features != ai_idev.hw_features)) { - zcmn_err(getzoneid(), CE_WARN, "lx_audio error: " - "audio device reported inconsistent features"); - return (EIO); - } - lxa_state->lxas_sw_features = ai_odev.sw_features; - lxa_state->lxas_hw_features = ai_odev.hw_features; - return (0); - } - - /* - * figure out which software features we're going to support. - * we will report a feature as supported if both the input - * and output device support it. - */ - lxa_state->lxas_sw_features = 0; - n = ai_idev.sw_features & ai_odev.sw_features; - if (n & AUDIO_SWFEATURE_MIXER) - lxa_state->lxas_sw_features |= AUDIO_SWFEATURE_MIXER; - - /* - * figure out which hardware features we're going to support. - * for a first pass we will report a feature as supported if - * both the input and output device support it. - */ - lxa_state->lxas_hw_features = 0; - n = ai_idev.hw_features & ai_odev.hw_features; - if (n & AUDIO_HWFEATURE_MSCODEC) - lxa_state->lxas_hw_features |= AUDIO_HWFEATURE_MSCODEC; - - /* - * if we made it here then we have different audio input and output - * devices. this will allow us to report support for additional - * hardware features that may not supported by just the input or - * output device alone. - */ - - /* always report tha we support both playback and recording */ - lxa_state->lxas_hw_features = - AUDIO_HWFEATURE_PLAY | AUDIO_HWFEATURE_RECORD; - - /* always report full duplex support */ - lxa_state->lxas_hw_features = AUDIO_HWFEATURE_DUPLEX; - - /* never report that we have input to output loopback support */ - ASSERT((lxa_state->lxas_hw_features & AUDIO_HWFEATURE_IN2OUT) == 0); - return (0); -} - -static int -lxa_dev_open(lxa_state_t *lxa_state) -{ - char *idev, *odev; - int flags, rv; - ldi_handle_t lh; - ldi_ident_t li = NULL; - - ASSERT((lxa_state->lxas_type == LXA_TYPE_AUDIO) || - (lxa_state->lxas_type == LXA_TYPE_AUDIOCTL)); - - /* - * check if we have configuration properties for this zone. - * if we don't then audio isn't supported in this zone. - */ - idev = lxa_devprop_lookup(getzonename(), LXA_PROP_INPUTDEV, - lxa_state->lxas_type); - odev = lxa_devprop_lookup(getzonename(), LXA_PROP_OUTPUTDEV, - lxa_state->lxas_type); - - /* make sure there is at least one device to read from or write to */ - if ((idev == NULL) && (odev == NULL)) - return (ENODEV); - - /* see if the input and output devices are actually the same device */ - if (((idev != NULL) && (odev != NULL)) && - (strcmp(idev, odev) == 0)) - lxa_state->lxas_devs_same = 1; - - /* we don't respect FEXCL */ - flags = lxa_state->lxas_flags & ~FEXCL; - if (lxa_state->lxas_type == LXA_TYPE_AUDIO) { - /* - * if we're opening audio devices then we need to muck - * with the FREAD/FWRITE flags. - * - * certain audio device may only support input or output - * (but not both.) so if we're multiplexing input/output - * to different devices we need to make sure we don't try - * and open the output device for reading and the input - * device for writing. - * - * if we're using the same device for input/output we still - * need to do this because some audio devices won't let - * themselves be opened multiple times for read access. - */ - lxa_state->lxas_idev_flags = flags & ~FWRITE; - lxa_state->lxas_odev_flags = flags & ~FREAD; - - /* make sure we have devices to read from and write to */ - if (((flags & FREAD) && (idev == NULL)) || - ((flags & FWRITE) && (odev == NULL))) { - rv = ENODEV; - goto out; - } - } else { - lxa_state->lxas_idev_flags = lxa_state->lxas_odev_flags = flags; - } - - /* get an ident to open the devices */ - if (ldi_ident_from_dev(lxa_state->lxas_dev_new, &li) != 0) { - rv = ENODEV; - goto out; - } - - /* open the input device */ - lxa_state->lxas_idev_lh = NULL; - if (((lxa_state->lxas_type == LXA_TYPE_AUDIOCTL) || - (lxa_state->lxas_idev_flags & FREAD)) && - (idev != NULL)) { - rv = ldi_open_by_name(idev, lxa_state->lxas_idev_flags, - kcred, &lh, li); - if (rv != 0) { - zcmn_err(getzoneid(), CE_WARN, "lxa_open_dev: " - "unable to open audio device: %s", idev); - zcmn_err(getzoneid(), CE_WARN, "lxa_open_dev: " - "possible zone audio configuration error"); - goto out; - } - lxa_state->lxas_idev_lh = lh; - } - - /* open the output device */ - lxa_state->lxas_odev_lh = NULL; - if (((lxa_state->lxas_type == LXA_TYPE_AUDIOCTL) || - (lxa_state->lxas_odev_flags & FWRITE)) && - (odev != NULL)) { - rv = ldi_open_by_name(odev, lxa_state->lxas_odev_flags, - kcred, &lh, li); - if (rv != 0) { - /* - * If this open failed and we previously opened an - * input device, it is the responsibility of the - * caller to close that device after we return - * failure here. - */ - zcmn_err(getzoneid(), CE_WARN, "lxa_open_dev: " - "unable to open audio device: %s", odev); - zcmn_err(getzoneid(), CE_WARN, "lxa_open_dev: " - "possible zone audio configuration error"); - goto out; - } - lxa_state->lxas_odev_lh = lh; - } - - /* free up stuff */ -out: - if (li != NULL) - ldi_ident_release(li); - if (idev != NULL) - strfree(idev); - if (odev != NULL) - strfree(odev); - - return (rv); -} - -void -lxa_mmap_thread_exit(lxa_state_t *lxa_state) -{ - mutex_enter(&lxa_lock); - lxa_state->lxas_mmap_thread = NULL; - lxa_state->lxas_mmap_thread_frag = 0; - lxa_state->lxas_mmap_thread_running = 0; - lxa_state->lxas_mmap_thread_exit = 0; - mutex_exit(&lxa_lock); - thread_exit(); - /*NOTREACHED*/ -} - -void -lxa_mmap_thread(lxa_state_t *lxa_state) -{ - struct uio uio, uio_null; - iovec_t iovec, iovec_null; - uint_t bytes_per_sec, usec_per_frag, ticks_per_frag; - int rv, junk, eof, retry; - audio_info_t ai; - - /* we better be setup for writing to the output device */ - ASSERT((lxa_state->lxas_flags & FWRITE) != 0); - ASSERT(lxa_state->lxas_odev_lh != NULL); - - /* setup a uio to output one fragment */ - uio.uio_iov = &iovec; - uio.uio_iovcnt = 1; - uio.uio_offset = 0; - uio.uio_segflg = UIO_SYSSPACE; - uio.uio_fmode = 0; - uio.uio_extflg = 0; - uio.uio_llimit = MAXOFFSET_T; - - /* setup a uio to output a eof (a fragment with a length of 0) */ - uio_null.uio_iov = &iovec_null; - uio_null.uio_iov->iov_len = 0; - uio_null.uio_iov->iov_base = NULL; - uio_null.uio_iovcnt = 1; - uio_null.uio_offset = 0; - uio_null.uio_segflg = UIO_SYSSPACE; - uio_null.uio_fmode = 0; - uio_null.uio_extflg = 0; - uio_null.uio_llimit = MAXOFFSET_T; - uio_null.uio_resid = 0; - -lxa_mmap_thread_top: - ASSERT(!MUTEX_HELD(&lxa_lock)); - - /* first drain any pending audio output */ - if ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, - AUDIO_DRAIN, NULL, FKIOCTL, kcred, &junk)) != 0) { - cmn_err(CE_WARN, "lxa_mmap_thread: " - "AUDIO_DRAIN failed, aborting audio output"); - lxa_mmap_thread_exit(lxa_state); - /*NOTREACHED*/ - } - - /* - * we depend on the ai.play.eof value to keep track of - * audio output progress so reset it here. - */ - AUDIO_INITINFO(&ai); - ai.play.eof = 0; - if ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, - AUDIO_SETINFO, (intptr_t)&ai, FKIOCTL, kcred, &junk)) != 0) { - cmn_err(CE_WARN, "lxa_mmap_thread: " - "AUDIO_SETINFO failed, aborting audio output"); - lxa_mmap_thread_exit(lxa_state); - /*NOTREACHED*/ - } - - /* - * we're going to need to know the sampling rate and number - * of output channels to estimate how long we can sleep between - * requests. - */ - if ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, AUDIO_GETINFO, - (intptr_t)&ai, FKIOCTL, kcred, &junk)) != 0) { - cmn_err(CE_WARN, "lxa_mmap_thread: " - "AUDIO_GETINFO failed, aborting audio output"); - lxa_mmap_thread_exit(lxa_state); - /*NOTREACHED*/ - } - - /* estimate how many ticks it takes to output a fragment of data */ - bytes_per_sec = (ai.play.sample_rate * ai.play.channels * - ai.play.precision) / 8; - usec_per_frag = MICROSEC * lxa_state->lxas_frag_size / bytes_per_sec; - ticks_per_frag = drv_usectohz(usec_per_frag); - - /* queue up three fragments of of data into the output stream */ - eof = 3; - - /* sanity check the eof value */ - ASSERT(ai.play.eof == 0); - ai.play.eof = 0; - - /* we always start audio output at fragment 0 */ - mutex_enter(&lxa_lock); - lxa_state->lxas_mmap_thread_frag = 0; - - /* - * we shouldn't have allowed the mapping if it isn't a multiple - * of the fragment size - */ - ASSERT((lxa_state->lxas_umem_len % lxa_state->lxas_frag_size) == 0); - - while (!lxa_state->lxas_mmap_thread_exit) { - size_t start, end; - - /* - * calculate the start and ending offsets of the next - * fragment to output - */ - start = lxa_state->lxas_mmap_thread_frag * - lxa_state->lxas_frag_size; - end = start + lxa_state->lxas_frag_size; - - ASSERT(start < lxa_state->lxas_umem_len); - ASSERT(end <= lxa_state->lxas_umem_len); - - /* setup the uio to output one fragment of audio */ - uio.uio_resid = end - start; - uio.uio_iov->iov_len = end - start; - uio.uio_iov->iov_base = &lxa_state->lxas_umem_ptr[start]; - - /* increment the current fragment index */ - lxa_state->lxas_mmap_thread_frag = - (lxa_state->lxas_mmap_thread_frag + 1) % - (lxa_state->lxas_umem_len / lxa_state->lxas_frag_size); - - /* drop the audio lock before actually outputting data */ - mutex_exit(&lxa_lock); - - /* - * write the fragment of audio data to the device stream - * then write a eof to the stream to tell the device to - * increment ai.play.eof when it's done processing the - * fragment we just wrote - */ - if ((rv = ldi_write(lxa_state->lxas_odev_lh, - &uio, kcred)) != 0) { - cmn_err(CE_WARN, "lxa_mmap_thread: " - "ldi_write() failed (%d), " - "resetting audio output", rv); - goto lxa_mmap_thread_top; - } - if ((rv = ldi_write(lxa_state->lxas_odev_lh, - &uio_null, kcred)) != 0) { - cmn_err(CE_WARN, "lxa_mmap_thread: " - "ldi_write(eof) failed (%d), " - "resetting audio output", rv); - goto lxa_mmap_thread_top; - } - - /* - * we want to avoid buffer underrun so ensure that - * there is always at least one fragment of data in the - * output stream. - */ - mutex_enter(&lxa_lock); - if (--eof > 0) { - continue; - } - - /* - * now we wait until the audio device has finished outputting - * at least one fragment of data. - */ - retry = 0; - while (!lxa_state->lxas_mmap_thread_exit && (eof == 0)) { - uint_t ai_eof_old = ai.play.eof; - - mutex_exit(&lxa_lock); - - /* - * delay for the number of ticks it takes - * to output one fragment of data - */ - if (ticks_per_frag > 0) - delay(ticks_per_frag); - - /* check if we've managed to output any fragments */ - if ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, - AUDIO_GETINFO, (intptr_t)&ai, - FKIOCTL, kcred, &junk)) != 0) { - cmn_err(CE_WARN, "lxa_mmap_thread: " - "AUDIO_GETINFO failed (%d), " - "resetting audio output", rv); - /* re-start mmap audio output */ - goto lxa_mmap_thread_top; - } - - if (ai_eof_old == ai.play.eof) { - /* institute a random retry limit */ - if (retry++ < 100) { - mutex_enter(&lxa_lock); - continue; - } - cmn_err(CE_WARN, "lxa_mmap_thread: " - "output stalled, " - "resetting audio output"); - /* re-start mmap audio output */ - goto lxa_mmap_thread_top; - } - - if (ai.play.eof > ai_eof_old) { - eof = ai.play.eof - ai_eof_old; - } else { - /* eof counter wrapped around */ - ASSERT(ai_eof_old < ai.play.eof); - eof = ai.play.eof + (ai_eof_old - UINTMAX_MAX); - } - /* we're done with this loop so re-aquire the lock */ - ASSERT(eof != 0); - mutex_enter(&lxa_lock); - } - } - mutex_exit(&lxa_lock); - lxa_mmap_thread_exit(lxa_state); - /*NOTREACHED*/ -} - -static void -lxa_mmap_output_disable(lxa_state_t *lxa_state) -{ - kt_did_t tid; - - mutex_enter(&lxa_lock); - - /* if the output thread isn't running there's nothing to do */ - if (lxa_state->lxas_mmap_thread_running == 0) { - mutex_exit(&lxa_lock); - return; - } - - /* tell the pcm mmap output thread to exit */ - lxa_state->lxas_mmap_thread_exit = 1; - - /* wait for the mmap output thread to exit */ - tid = lxa_state->lxas_mmap_thread->t_did; - mutex_exit(&lxa_lock); - thread_join(tid); -} - -static void -lxa_mmap_output_enable(lxa_state_t *lxa_state) -{ - mutex_enter(&lxa_lock); - - /* if the output thread is already running there's nothing to do */ - if (lxa_state->lxas_mmap_thread_running != 0) { - mutex_exit(&lxa_lock); - return; - } - - /* setup output state */ - lxa_state->lxas_mmap_thread_running = 1; - lxa_state->lxas_mmap_thread_exit = 0; - lxa_state->lxas_mmap_thread_frag = 0; - - /* kick off a thread to do the mmap pcm output */ - lxa_state->lxas_mmap_thread = thread_create(NULL, 0, - (void (*)())lxa_mmap_thread, lxa_state, - 0, &p0, TS_RUN, minclsyspri); - ASSERT(lxa_state->lxas_mmap_thread != NULL); - - mutex_exit(&lxa_lock); -} - -static int -lxa_ioc_mmap_output(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - uint_t trigger; - - /* we only support output via mmap */ - if ((lxa_state->lxas_flags & FWRITE) == 0) - return (EINVAL); - - /* if the user hasn't mmap the device then there's nothing to do */ - if (lxa_state->lxas_umem_cookie == NULL) - return (EINVAL); - - /* copy in the request */ - if (ddi_copyin((void *)arg, &trigger, sizeof (trigger), mode) != 0) - return (EFAULT); - - /* a zero value disables output */ - if (trigger == 0) { - lxa_mmap_output_disable(lxa_state); - return (0); - } - - /* a non-zero value enables output */ - lxa_mmap_output_enable(lxa_state); - return (0); -} - -static int -lxa_ioc_mmap_ptr(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - int ptr; - - /* we only support output via mmap */ - if ((lxa_state->lxas_flags & FWRITE) == 0) - return (EINVAL); - - /* if the user hasn't mmap the device then there's nothing to do */ - if (lxa_state->lxas_umem_cookie == NULL) - return (EINVAL); - - /* if the output thread isn't running then there's nothing to do */ - if (lxa_state->lxas_mmap_thread_running == 0) - return (EINVAL); - - mutex_enter(&lxa_lock); - ptr = lxa_state->lxas_mmap_thread_frag * lxa_state->lxas_frag_size; - mutex_exit(&lxa_lock); - - if (ddi_copyout(&ptr, (void *)arg, sizeof (ptr), mode) != 0) - return (EFAULT); - - return (0); -} - -static int -lxa_ioc_get_frag_info(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - lxa_frag_info_t fi; - - fi.lxa_fi_size = lxa_state->lxas_frag_size; - fi.lxa_fi_cnt = lxa_state->lxas_frag_cnt; - - if (ddi_copyout(&fi, (void *)arg, sizeof (fi), mode) != 0) - return (EFAULT); - - return (0); -} - -static int -lxa_ioc_set_frag_info(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - lxa_frag_info_t fi; - - /* if the device is mmaped we can't change the fragment settings */ - if (lxa_state->lxas_umem_cookie != NULL) - return (EINVAL); - - /* copy in the request */ - if (ddi_copyin((void *)arg, &fi, sizeof (fi), mode) != 0) - return (EFAULT); - - /* do basic bounds checking */ - if ((fi.lxa_fi_cnt == 0) || (fi.lxa_fi_size < 16)) - return (EINVAL); - - /* don't accept size values less than 16 */ - - lxa_state->lxas_frag_size = fi.lxa_fi_size; - lxa_state->lxas_frag_cnt = fi.lxa_fi_cnt; - - return (0); -} - -static int -lxa_audio_drain(lxa_state_t *lxa_state) -{ - int junk; - - /* only applies to output buffers */ - if (lxa_state->lxas_odev_lh == NULL) - return (EINVAL); - - /* can't fail so ignore the return value */ - (void) ldi_ioctl(lxa_state->lxas_odev_lh, AUDIO_DRAIN, NULL, - FKIOCTL, kcred, &junk); - return (0); -} - -/* - * lxa_audio_info_merge() usage notes: - * - * - it's important to make sure NOT to get the ai_idev and ai_odev - * parameters mixed up when calling lxa_audio_info_merge(). - * - * - it's important for the caller to make sure that AUDIO_GETINFO - * was called for the input device BEFORE the output device. (see - * the comments for merging the monitor_gain setting to see why.) - */ -static void -lxa_audio_info_merge(lxa_state_t *lxa_state, - audio_info_t *ai_idev, audio_info_t *ai_odev, audio_info_t *ai_merged) -{ - /* if we're not setup for output return the intput device info */ - if (lxa_state->lxas_odev_lh == NULL) { - *ai_merged = *ai_idev; - return; - } - - /* if we're not setup for input return the output device info */ - if (lxa_state->lxas_idev_lh == NULL) { - *ai_merged = *ai_odev; - return; - } - - /* get record values from the input device */ - ai_merged->record = ai_idev->record; - - /* get play values from the output device */ - ai_merged->play = ai_odev->play; - - /* muting status only matters for the output device */ - ai_merged->output_muted = ai_odev->output_muted; - - /* we don't support device reference counts, always return 1 */ - ai_merged->ref_cnt = 1; - - /* - * for supported hw/sw features report the combined feature - * set we calcuated out earlier. - */ - ai_merged->hw_features = lxa_state->lxas_hw_features; - ai_merged->sw_features = lxa_state->lxas_sw_features; - - if (!lxa_state->lxas_devs_same) { - /* - * if the input and output devices are different - * physical devices then we don't support input to - * output loopback so we always report the input - * to output loopback gain to be zero. - */ - ai_merged->monitor_gain = 0; - } else { - /* - * the intput and output devices are actually the - * same physical device. hence it probably supports - * intput to output loopback. regardless we should - * pass back the intput to output gain reported by - * the device. when we pick a value to passback we - * use the output device value since that was - * the most recently queried. (we base this - * decision on the assumption that io gain is - * actually hardware setting in the device and - * hence if it is changed on one open instance of - * the device the change will be visable to all - * other instances of the device.) - */ - ai_merged->monitor_gain = ai_odev->monitor_gain; - } - - /* - * for currently enabled software features always return the - * merger of the two. (of course the enabled software features - * for the input and output devices should alway be the same, - * so if it isn't complain.) - */ - if (ai_idev->sw_features_enabled != ai_odev->sw_features_enabled) - zcmn_err(getzoneid(), CE_WARN, "lx_audio: " - "unexpected sofware feature state"); - ai_merged->sw_features_enabled = - ai_idev->sw_features_enabled & ai_odev->sw_features_enabled; -} - -static int -lxa_audio_setinfo(lxa_state_t *lxa_state, int cmd, intptr_t arg, - int mode) -{ - audio_info_t ai, ai_null, ai_idev, ai_odev; - int rv, junk; - - /* copy in the request */ - if (ddi_copyin((void *)arg, &ai, sizeof (ai), mode) != 0) - return (EFAULT); - - /* - * if the caller is attempting to enable a software feature that - * we didn't report as supported the return an error - */ - if ((ai.sw_features_enabled != -1) && - (ai.sw_features_enabled & ~lxa_state->lxas_sw_features)) - return (EINVAL); - - /* - * if a process has mmaped this device then we don't allow - * changes to the play.eof field (since mmap output depends - * on this field. - */ - if ((lxa_state->lxas_umem_cookie != NULL) && - (ai.play.eof != -1)) - return (EIO); - - /* initialize the new requests */ - AUDIO_INITINFO(&ai_null); - ai_idev = ai_odev = ai; - - /* remove audio input settings from the output device request */ - ai_odev.record = ai_null.record; - - /* remove audio output settings from the input device request */ - ai_idev.play = ai_null.play; - ai_idev.output_muted = ai_null.output_muted; - - /* apply settings to the intput device */ - if ((lxa_state->lxas_idev_lh != NULL) && - ((rv = ldi_ioctl(lxa_state->lxas_idev_lh, cmd, - (intptr_t)&ai_idev, FKIOCTL, kcred, &junk)) != 0)) - return (rv); - - /* apply settings to the output device */ - if ((lxa_state->lxas_odev_lh != NULL) && - ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, cmd, - (intptr_t)&ai_odev, FKIOCTL, kcred, &junk)) != 0)) - return (rv); - - /* - * a AUDIO_SETINFO call performs an implicit AUDIO_GETINFO to - * return values (see the coments in audioio.h.) so we need - * to combine the values returned from the input and output - * device back into the users buffer. - */ - lxa_audio_info_merge(lxa_state, &ai_idev, &ai_odev, &ai); - - /* copyout the results */ - if (ddi_copyout(&ai, (void *)arg, sizeof (ai), mode) != 0) { - return (EFAULT); - } - - return (0); -} - -static int -lxa_audio_getinfo(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - audio_info_t ai, ai_idev, ai_odev; - int rv, junk; - - /* get the settings from the input device */ - if ((lxa_state->lxas_idev_lh != NULL) && - ((rv = ldi_ioctl(lxa_state->lxas_idev_lh, AUDIO_GETINFO, - (intptr_t)&ai_idev, FKIOCTL, kcred, &junk)) != 0)) - return (rv); - - /* get the settings from the output device */ - if ((lxa_state->lxas_odev_lh != NULL) && - ((rv = ldi_ioctl(lxa_state->lxas_odev_lh, AUDIO_GETINFO, - (intptr_t)&ai_odev, FKIOCTL, kcred, &junk)) != 0)) - return (rv); - - /* - * we need to combine the values returned from the input - * and output device back into a single user buffer. - */ - lxa_audio_info_merge(lxa_state, &ai_idev, &ai_odev, &ai); - - /* copyout the results */ - if (ddi_copyout(&ai, (void *)arg, sizeof (ai), mode) != 0) - return (EFAULT); - - return (0); -} - -static int -lxa_mixer_ai_from_lh(ldi_handle_t lh, audio_info_t *ai) -{ - int rv, junk; - - ASSERT((lh != NULL) && (ai != NULL)); - - /* get the device state and channel state */ - rv = ldi_ioctl(lh, AUDIO_GETINFO, (intptr_t)ai, FKIOCTL, kcred, &junk); - - return (rv); -} - -static int -lxa_mixer_get_ai(lxa_state_t *lxa_state, audio_info_t *ai) -{ - audio_info_t ai_idev, ai_odev; - int rv; - - /* if there is no input device, query the output device */ - if (lxa_state->lxas_idev_lh == NULL) - return (lxa_mixer_ai_from_lh(lxa_state->lxas_odev_lh, ai)); - - /* if there is no ouput device, query the intput device */ - if (lxa_state->lxas_odev_lh == NULL) - return (lxa_mixer_ai_from_lh(lxa_state->lxas_idev_lh, ai)); - - /* - * now get the audio_info and channel information for the - * underlying output device. - */ - if ((rv = lxa_mixer_ai_from_lh(lxa_state->lxas_idev_lh, - &ai_idev)) != 0) - return (rv); - if ((rv = lxa_mixer_ai_from_lh(lxa_state->lxas_odev_lh, - &ai_odev)) != 0) - return (rv); - - /* now merge the audio_info structures */ - lxa_audio_info_merge(lxa_state, &ai_idev, &ai_odev, ai); - return (0); -} - -static int -lxa_mixer_get_common(lxa_state_t *lxa_state, int cmd, intptr_t arg, int mode) -{ - lxa_mixer_levels_t lxa_ml; - audio_info_t ai; - int rv; - - ASSERT(lxa_state->lxas_type == LXA_TYPE_AUDIOCTL); - - if ((rv = lxa_mixer_get_ai(lxa_state, &ai)) != 0) - return (rv); - - switch (cmd) { - case LXA_IOC_MIXER_GET_VOL: - lxa_ml.lxa_ml_gain = ai.play.gain; - lxa_ml.lxa_ml_balance = ai.play.balance; - break; - case LXA_IOC_MIXER_GET_MIC: - lxa_ml.lxa_ml_gain = ai.record.gain; - lxa_ml.lxa_ml_balance = ai.record.balance; - break; - } - - if (ddi_copyout(&lxa_ml, (void *)arg, sizeof (lxa_ml), mode) != 0) - return (EFAULT); - return (0); -} - -static int -lxa_mixer_set_common(lxa_state_t *lxa_state, int cmd, intptr_t arg, int mode) -{ - lxa_mixer_levels_t lxa_ml; - audio_info_t ai; - - ASSERT(lxa_state->lxas_type == LXA_TYPE_AUDIOCTL); - - /* get the new mixer settings */ - if (ddi_copyin((void *)arg, &lxa_ml, sizeof (lxa_ml), mode) != 0) - return (EFAULT); - - /* sanity check the mixer settings */ - if (!LXA_MIXER_LEVELS_OK(&lxa_ml)) - return (EINVAL); - - /* initialize an audio_info struct with the new settings */ - AUDIO_INITINFO(&ai); - switch (cmd) { - case LXA_IOC_MIXER_SET_VOL: - ai.play.gain = lxa_ml.lxa_ml_gain; - ai.play.balance = lxa_ml.lxa_ml_balance; - break; - case LXA_IOC_MIXER_SET_MIC: - ai.record.gain = lxa_ml.lxa_ml_gain; - ai.record.balance = lxa_ml.lxa_ml_balance; - break; - } - - return (lxa_audio_setinfo(lxa_state, AUDIO_SETINFO, (intptr_t)&ai, - FKIOCTL)); -} - -static int -lxa_mixer_get_pcm(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - ASSERT(lxa_state->lxas_type == LXA_TYPE_AUDIOCTL); - - /* simply return the cached pcm mixer settings */ - mutex_enter(&lxa_lock); - if (ddi_copyout(&lxa_state->lxas_zs->lxa_zs_pcm_levels, (void *)arg, - sizeof (lxa_state->lxas_zs->lxa_zs_pcm_levels), mode) != 0) { - mutex_exit(&lxa_lock); - return (EFAULT); - } - mutex_exit(&lxa_lock); - return (0); -} - -static int -lxa_mixer_set_pcm(lxa_state_t *lxa_state, intptr_t arg, int mode) -{ - lxa_mixer_levels_t lxa_ml; - int rv; - - ASSERT(lxa_state->lxas_type == LXA_TYPE_AUDIOCTL); - - /* get the new mixer settings */ - if (ddi_copyin((void *)arg, &lxa_ml, sizeof (lxa_ml), mode) != 0) - return (EFAULT); - - /* sanity check the mixer settings */ - if (!LXA_MIXER_LEVELS_OK(&lxa_ml)) - return (EINVAL); - - mutex_enter(&lxa_lock); - - /* if there is an active output channel, update it */ - if (lxa_state->lxas_zs->lxa_zs_ostate != NULL) { - audio_info_t ai; - - /* initialize an audio_info struct with the new settings */ - AUDIO_INITINFO(&ai); - ai.play.gain = lxa_ml.lxa_ml_gain; - ai.play.balance = lxa_ml.lxa_ml_balance; - - if ((rv = lxa_audio_setinfo(lxa_state->lxas_zs->lxa_zs_ostate, - AUDIO_SETINFO, (intptr_t)&ai, FKIOCTL)) != 0) { - mutex_exit(&lxa_lock); - return (rv); - } - } - - /* update the cached mixer settings */ - lxa_state->lxas_zs->lxa_zs_pcm_levels = lxa_ml; - - mutex_exit(&lxa_lock); - return (0); -} - -static int -lxa_zone_reg(intptr_t arg, int mode) -{ - lxa_zone_reg_t lxa_zr; - lxa_zstate_t *lxa_zs = NULL; - char *idev_name = NULL, *odev_name = NULL, *pval = NULL; - int i, junk; - - if (ddi_copyin((void *)arg, &lxa_zr, sizeof (lxa_zr), mode) != 0) - return (EFAULT); - - /* make sure that zone_name is a valid string */ - for (i = 0; i < sizeof (lxa_zr.lxa_zr_zone_name); i++) - if (lxa_zr.lxa_zr_zone_name[i] == '\0') - break; - if (i == sizeof (lxa_zr.lxa_zr_zone_name)) - return (EINVAL); - - /* make sure that inputdev is a valid string */ - for (i = 0; i < sizeof (lxa_zr.lxa_zr_inputdev); i++) - if (lxa_zr.lxa_zr_inputdev[i] == '\0') - break; - if (i == sizeof (lxa_zr.lxa_zr_inputdev)) - return (EINVAL); - - /* make sure it's a valid inputdev property value */ - if (lxa_devprop_verify(lxa_zr.lxa_zr_inputdev) != 0) - return (EINVAL); - - /* make sure that outputdev is a valid string */ - for (i = 0; i < sizeof (lxa_zr.lxa_zr_outputdev); i++) - if (lxa_zr.lxa_zr_outputdev[i] == '\0') - break; - if (i == sizeof (lxa_zr.lxa_zr_outputdev)) - return (EINVAL); - - /* make sure it's a valid outputdev property value */ - if (lxa_devprop_verify(lxa_zr.lxa_zr_outputdev) != 0) - return (EINVAL); - - /* get the property names */ - idev_name = lxa_devprop_name(lxa_zr.lxa_zr_zone_name, - LXA_PROP_INPUTDEV); - odev_name = lxa_devprop_name(lxa_zr.lxa_zr_zone_name, - LXA_PROP_OUTPUTDEV); - - /* - * allocate and initialize a zone state structure - * since the audio device can't possibly be opened yet - * (since we're setting it up now and the zone isn't booted - * yet) assign some some resonable default pcm channel settings. - * also, default to one mixer channel. - */ - lxa_zs = kmem_zalloc(sizeof (*lxa_zs), KM_SLEEP); - lxa_zs->lxa_zs_zonename = strdup(lxa_zr.lxa_zr_zone_name); - lxa_zs->lxa_zs_pcm_levels.lxa_ml_gain = AUDIO_MID_GAIN; - lxa_zs->lxa_zs_pcm_levels.lxa_ml_balance = AUDIO_MID_BALANCE; - - mutex_enter(&lxa_lock); - - /* - * make sure this zone isn't already registered - * a zone is registered with properties for that zone exist - * or there is a zone state structure for that zone - */ - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lxa_dip, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - idev_name, &pval) == DDI_PROP_SUCCESS) { - goto err_unlock; - } - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lxa_dip, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - odev_name, &pval) == DDI_PROP_SUCCESS) { - goto err_unlock; - } - if (mod_hash_find(lxa_zstate_hash, - (mod_hash_key_t)lxa_zs->lxa_zs_zonename, - (mod_hash_val_t *)&junk) == 0) - goto err_unlock; - - /* - * create the new properties and insert the zone state structure - * into the global hash - */ - if (ddi_prop_update_string(DDI_DEV_T_NONE, lxa_dip, - idev_name, lxa_zr.lxa_zr_inputdev) != DDI_PROP_SUCCESS) - goto err_prop_remove; - if (ddi_prop_update_string(DDI_DEV_T_NONE, lxa_dip, - odev_name, lxa_zr.lxa_zr_outputdev) != DDI_PROP_SUCCESS) - goto err_prop_remove; - if (mod_hash_insert(lxa_zstate_hash, - (mod_hash_key_t)lxa_zs->lxa_zs_zonename, - (mod_hash_val_t)lxa_zs) != 0) - goto err_prop_remove; - - /* success! */ - lxa_registered_zones++; - mutex_exit(&lxa_lock); - - /* cleanup */ - strfree(idev_name); - strfree(odev_name); - return (0); - -err_prop_remove: - (void) ddi_prop_remove(DDI_DEV_T_NONE, lxa_dip, idev_name); - (void) ddi_prop_remove(DDI_DEV_T_NONE, lxa_dip, odev_name); - -err_unlock: - mutex_exit(&lxa_lock); - - if (lxa_zs != NULL) { - strfree(lxa_zs->lxa_zs_zonename); - kmem_free(lxa_zs, sizeof (*lxa_zs)); - } - if (pval != NULL) - ddi_prop_free(pval); - if (idev_name != NULL) - strfree(idev_name); - if (odev_name != NULL) - strfree(odev_name); - return (EIO); -} - -static int -lxa_zone_unreg(intptr_t arg, int mode) -{ - lxa_zone_reg_t lxa_zr; - lxa_zstate_t *lxa_zs = NULL; - char *idev_name = NULL, *odev_name = NULL, *pval = NULL; - int rv, i; - - if (ddi_copyin((void *)arg, &lxa_zr, sizeof (lxa_zr), mode) != 0) - return (EFAULT); - - /* make sure that zone_name is a valid string */ - for (i = 0; i < sizeof (lxa_zr.lxa_zr_zone_name); i++) - if (lxa_zr.lxa_zr_zone_name[i] == '\0') - break; - if (i == sizeof (lxa_zr.lxa_zr_zone_name)) - return (EINVAL); - - /* get the property names */ - idev_name = lxa_devprop_name(lxa_zr.lxa_zr_zone_name, - LXA_PROP_INPUTDEV); - odev_name = lxa_devprop_name(lxa_zr.lxa_zr_zone_name, - LXA_PROP_OUTPUTDEV); - - mutex_enter(&lxa_lock); - - if (lxa_registered_zones <= 0) { - rv = ENOENT; - goto err_unlock; - } - - /* make sure this zone is actually registered */ - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lxa_dip, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - idev_name, &pval) != DDI_PROP_SUCCESS) { - rv = ENOENT; - goto err_unlock; - } - ddi_prop_free(pval); - pval = NULL; - if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lxa_dip, - DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, - odev_name, &pval) != DDI_PROP_SUCCESS) { - rv = ENOENT; - goto err_unlock; - } - ddi_prop_free(pval); - pval = NULL; - if (mod_hash_find(lxa_zstate_hash, - (mod_hash_key_t)lxa_zr.lxa_zr_zone_name, - (mod_hash_val_t *)&lxa_zs) != 0) { - rv = ENOENT; - goto err_unlock; - } - ASSERT(strcmp(lxa_zr.lxa_zr_zone_name, lxa_zs->lxa_zs_zonename) == 0); - - /* - * if the audio device is currently in use then refuse to - * unregister the zone - */ - if ((lxa_zs->lxa_zs_ostate != NULL) || - (lxa_zs->lxa_zs_ostate != NULL)) { - rv = EBUSY; - goto err_unlock; - } - - /* success! cleanup zone config state */ - (void) ddi_prop_remove(DDI_DEV_T_NONE, lxa_dip, idev_name); - (void) ddi_prop_remove(DDI_DEV_T_NONE, lxa_dip, odev_name); - - /* - * note, the action of removing the zone state structure from the - * hash will automatically free lxa_zs->lxa_zs_zonename. - * - * the reason for this is that we used lxa_zs->lxa_zs_zonename - * as the hash key and by default mod_hash_create_strhash() uses - * mod_hash_strkey_dtor() as a the hash key destructor. (which - * free's the key for us. - */ - (void) mod_hash_remove(lxa_zstate_hash, - (mod_hash_key_t)lxa_zr.lxa_zr_zone_name, - (mod_hash_val_t *)&lxa_zs); - lxa_registered_zones--; - mutex_exit(&lxa_lock); - - /* cleanup */ - kmem_free(lxa_zs, sizeof (*lxa_zs)); - strfree(idev_name); - strfree(odev_name); - return (0); - -err_unlock: - mutex_exit(&lxa_lock); - - if (pval != NULL) - ddi_prop_free(pval); - if (idev_name != NULL) - strfree(idev_name); - if (odev_name != NULL) - strfree(odev_name); - return (rv); -} - -static int -lxa_ioctl_devctl(int cmd, intptr_t arg, int mode) -{ - /* devctl ioctls are only allowed from the global zone */ - ASSERT(getzoneid() == 0); - if (getzoneid() != 0) - return (EINVAL); - - switch (cmd) { - case LXA_IOC_ZONE_REG: - return (lxa_zone_reg(arg, mode)); - case LXA_IOC_ZONE_UNREG: - return (lxa_zone_unreg(arg, mode)); - } - - return (EINVAL); -} - -static int -/*ARGSUSED*/ -lxa_open(dev_t *devp, int flags, int otyp, cred_t *credp) -{ - lxa_dev_type_t open_type = LXA_TYPE_INVALID; - lxa_zstate_t *lxa_zs; - lxa_state_t *lxa_state; - minor_t minor; - int rv; - - if (getminor(*devp) == LXA_MINORNUM_DEVCTL) { - /* - * this is a devctl node, it exists to administer this - * pseudo driver so it doesn't actually need access to - * any underlying audio devices. hence there is nothing - * really to do here. course, this driver should - * only be administered from the global zone. - */ - ASSERT(getzoneid() == 0); - if (getzoneid() != 0) - return (EINVAL); - return (0); - } - - /* lookup the zone state structure */ - if (mod_hash_find(lxa_zstate_hash, (mod_hash_key_t)getzonename(), - (mod_hash_val_t *)&lxa_zs) != 0) { - return (EIO); - } - - /* determine what type of device was opened */ - switch (getminor(*devp)) { - case LXA_MINORNUM_DSP: - open_type = LXA_TYPE_AUDIO; - break; - case LXA_MINORNUM_MIXER: - open_type = LXA_TYPE_AUDIOCTL; - break; - default: - return (EINVAL); - } - ASSERT(open_type != LXA_TYPE_INVALID); - - /* all other opens are clone opens so get a new minor node */ - minor = id_alloc(lxa_minor_id); - - /* allocate and initialize the new lxa_state structure */ - lxa_state = kmem_zalloc(sizeof (*lxa_state), KM_SLEEP); - lxa_state->lxas_zs = lxa_zs; - lxa_state->lxas_dev_old = *devp; - lxa_state->lxas_dev_new = makedevice(getmajor(*devp), minor); - lxa_state->lxas_flags = flags; - lxa_state->lxas_type = open_type; - - /* initialize the input and output device */ - if (((rv = lxa_dev_open(lxa_state)) != 0) || - ((rv = lxa_dev_getfeatures(lxa_state)) != 0)) { - lxa_state_close(lxa_state); - return (rv); - } - - /* - * save this audio statue structure into a hash indexed - * by it's minor device number. (this will provide a convient - * way to lookup the state structure on future operations.) - */ - if (mod_hash_insert(lxa_state_hash, (mod_hash_key_t)(uintptr_t)minor, - (mod_hash_val_t)lxa_state) != 0) { - lxa_state_close(lxa_state); - return (EIO); - } - - mutex_enter(&lxa_lock); - - /* apply the currently cached zone PCM mixer levels */ - if ((lxa_state->lxas_type == LXA_TYPE_AUDIO) && - (lxa_state->lxas_odev_lh != NULL)) { - audio_info_t ai; - - AUDIO_INITINFO(&ai); - ai.play.gain = lxa_zs->lxa_zs_pcm_levels.lxa_ml_gain; - ai.play.balance = lxa_zs->lxa_zs_pcm_levels.lxa_ml_balance; - - if ((rv = lxa_audio_setinfo(lxa_state, - AUDIO_SETINFO, (intptr_t)&ai, FKIOCTL)) != 0) { - mutex_exit(&lxa_lock); - lxa_state_close(lxa_state); - return (rv); - } - } - - /* - * we only allow one active open of the input or output device. - * check here for duplicate opens - */ - if (lxa_state->lxas_type == LXA_TYPE_AUDIO) { - if ((lxa_state->lxas_idev_lh != NULL) && - (lxa_zs->lxa_zs_istate != NULL)) { - mutex_exit(&lxa_lock); - lxa_state_close(lxa_state); - return (EBUSY); - } - if ((lxa_state->lxas_odev_lh != NULL) && - (lxa_zs->lxa_zs_ostate != NULL)) { - mutex_exit(&lxa_lock); - lxa_state_close(lxa_state); - return (EBUSY); - } - - /* not a duplicate open, update the global zone state */ - if (lxa_state->lxas_idev_lh != NULL) - lxa_zs->lxa_zs_istate = lxa_state; - if (lxa_state->lxas_odev_lh != NULL) - lxa_zs->lxa_zs_ostate = lxa_state; - } - mutex_exit(&lxa_lock); - - /* make sure to return our newly allocated dev_t */ - *devp = lxa_state->lxas_dev_new; - return (0); -} - -static int -/*ARGSUSED*/ -lxa_close(dev_t dev, int flags, int otyp, cred_t *credp) -{ - lxa_state_t *lxa_state; - minor_t minor = getminor(dev); - - /* handle devctl minor nodes (these nodes don't have a handle */ - if (getminor(dev) == LXA_MINORNUM_DEVCTL) - return (0); - - /* get the handle for this device */ - if (mod_hash_find(lxa_state_hash, (mod_hash_key_t)(uintptr_t)minor, - (mod_hash_val_t *)&lxa_state) != 0) - return (EINVAL); - - lxa_state_close(lxa_state); - return (0); -} - -static int -/*ARGSUSED*/ -lxa_read(dev_t dev, struct uio *uiop, cred_t *credp) -{ - lxa_state_t *lxa_state; - minor_t minor = getminor(dev); - int rv; - - /* get the handle for this device */ - if (mod_hash_find(lxa_state_hash, (mod_hash_key_t)(uintptr_t)minor, - (mod_hash_val_t *)&lxa_state) != 0) - return (EINVAL); - - /* - * if a process has mmaped this device then we don't allow - * any more reads or writes to the device - */ - if (lxa_state->lxas_umem_cookie != NULL) - return (EIO); - - /* we can't do a read if there is no input device */ - if (lxa_state->lxas_idev_lh == NULL) - return (EBADF); - - /* pass the request on */ - while (uiop->uio_resid != 0) { - rv = ldi_read(lxa_state->lxas_idev_lh, uiop, kcred); - if ((rv != 0) || (uiop->uio_fmode & (FNONBLOCK|FNDELAY))) { - break; - } - } - return (rv); -} - -static int -/*ARGSUSED*/ -lxa_write(dev_t dev, struct uio *uiop, cred_t *credp) -{ - lxa_state_t *lxa_state; - minor_t minor = getminor(dev); - int rv; - - /* get the handle for this device */ - if (mod_hash_find(lxa_state_hash, (mod_hash_key_t)(uintptr_t)minor, - (mod_hash_val_t *)&lxa_state) != 0) - return (EINVAL); - - /* - * if a process has mmaped this device then we don't allow - * any more reads or writes to the device - */ - if (lxa_state->lxas_umem_cookie != NULL) - return (EIO); - - /* we can't do a write if there is no output device */ - if (lxa_state->lxas_odev_lh == NULL) - return (EBADF); - - /* pass the request on */ - while (uiop->uio_resid != 0) { - rv = ldi_write(lxa_state->lxas_odev_lh, uiop, kcred); - if ((rv != 0) || (uiop->uio_fmode & (FNONBLOCK|FNDELAY))) { - break; - } - } - return (rv); -} - -static int -/*ARGSUSED*/ -lxa_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, - int *rvalp) -{ - lxa_state_t *lxa_state; - minor_t minor = getminor(dev); - - /* handle devctl minor nodes (these nodes don't have a handle */ - if (getminor(dev) == LXA_MINORNUM_DEVCTL) - return (lxa_ioctl_devctl(cmd, arg, mode)); - - /* get the handle for this device */ - if (mod_hash_find(lxa_state_hash, (mod_hash_key_t)(uintptr_t)minor, - (mod_hash_val_t *)&lxa_state) != 0) - return (EINVAL); - - ASSERT((lxa_state->lxas_type == LXA_TYPE_AUDIO) || - (lxa_state->lxas_type == LXA_TYPE_AUDIOCTL)); - - switch (cmd) { - case LXA_IOC_GETMINORNUM: - { - int minornum = getminor(lxa_state->lxas_dev_old); - if (ddi_copyout(&minornum, (void *)arg, - sizeof (minornum), mode) != 0) - return (EFAULT); - } - return (0); - } - - if (lxa_state->lxas_type == LXA_TYPE_AUDIO) { - /* deal with native ioctl */ - switch (cmd) { - case LXA_IOC_MMAP_OUTPUT: - return (lxa_ioc_mmap_output(lxa_state, arg, mode)); - case LXA_IOC_MMAP_PTR: - return (lxa_ioc_mmap_ptr(lxa_state, arg, mode)); - case LXA_IOC_GET_FRAG_INFO: - return (lxa_ioc_get_frag_info(lxa_state, arg, mode)); - case LXA_IOC_SET_FRAG_INFO: - return (lxa_ioc_set_frag_info(lxa_state, arg, mode)); - } - - /* deal with layered ioctls */ - switch (cmd) { - case AUDIO_DRAIN: - return (lxa_audio_drain(lxa_state)); - case AUDIO_SETINFO: - return (lxa_audio_setinfo(lxa_state, - AUDIO_SETINFO, arg, mode)); - case AUDIO_GETINFO: - return (lxa_audio_getinfo(lxa_state, arg, mode)); - } - } - - if (lxa_state->lxas_type == LXA_TYPE_AUDIOCTL) { - /* deal with native ioctl */ - switch (cmd) { - case LXA_IOC_MIXER_GET_VOL: - return (lxa_mixer_get_common(lxa_state, - cmd, arg, mode)); - case LXA_IOC_MIXER_SET_VOL: - return (lxa_mixer_set_common(lxa_state, - cmd, arg, mode)); - case LXA_IOC_MIXER_GET_MIC: - return (lxa_mixer_get_common(lxa_state, - cmd, arg, mode)); - case LXA_IOC_MIXER_SET_MIC: - return (lxa_mixer_set_common(lxa_state, - cmd, arg, mode)); - case LXA_IOC_MIXER_GET_PCM: - return (lxa_mixer_get_pcm(lxa_state, arg, mode)); - case LXA_IOC_MIXER_SET_PCM: - return (lxa_mixer_set_pcm(lxa_state, arg, mode)); - } - - } - - return (EINVAL); -} - -static int -/*ARGSUSED*/ -lxa_devmap(dev_t dev, devmap_cookie_t dhp, - offset_t off, size_t len, size_t *maplen, uint_t model) -{ - lxa_state_t *lxa_state; - minor_t minor = getminor(dev); - ddi_umem_cookie_t umem_cookie; - void *umem_ptr; - int rv; - - /* get the handle for this device */ - if (mod_hash_find(lxa_state_hash, (mod_hash_key_t)(uintptr_t)minor, - (mod_hash_val_t *)&lxa_state) != 0) - return (EINVAL); - - /* we only support mmaping of audio devices */ - if (lxa_state->lxas_type != LXA_TYPE_AUDIO) - return (EINVAL); - - /* we only support output via mmap */ - if ((lxa_state->lxas_flags & FWRITE) == 0) - return (EINVAL); - - /* sanity check the amount of memory the user is allocating */ - if ((len == 0) || - (len > LXA_OSS_FRAG_MEM) || - ((len % lxa_state->lxas_frag_size) != 0)) - return (EINVAL); - - /* allocate and clear memory to mmap */ - umem_ptr = ddi_umem_alloc(len, DDI_UMEM_NOSLEEP, &umem_cookie); - if (umem_ptr == NULL) - return (ENOMEM); - bzero(umem_ptr, len); - - /* setup the memory mappings */ - rv = devmap_umem_setup(dhp, lxa_dip, NULL, umem_cookie, 0, len, - PROT_USER | PROT_READ | PROT_WRITE, 0, NULL); - if (rv != 0) { - ddi_umem_free(umem_cookie); - return (EIO); - } - - mutex_enter(&lxa_lock); - - /* we only support one mmap per open */ - if (lxa_state->lxas_umem_cookie != NULL) { - ASSERT(lxa_state->lxas_umem_ptr != NULL); - mutex_exit(&lxa_lock); - ddi_umem_free(umem_cookie); - return (EBUSY); - } - ASSERT(lxa_state->lxas_umem_ptr == NULL); - - *maplen = len; - lxa_state->lxas_umem_len = len; - lxa_state->lxas_umem_ptr = umem_ptr; - lxa_state->lxas_umem_cookie = umem_cookie; - mutex_exit(&lxa_lock); - return (0); -} - -static int -/*ARGSUSED*/ -lxa_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - int instance = ddi_get_instance(dip); - - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - ASSERT(instance == 0); - if (instance != 0) - return (DDI_FAILURE); - - lxa_dip = dip; - mutex_init(&lxa_lock, NULL, MUTEX_DEFAULT, NULL); - - /* create our minor nodes */ - if (ddi_create_minor_node(dip, LXA_MINORNAME_DEVCTL, S_IFCHR, - LXA_MINORNUM_DEVCTL, DDI_PSEUDO, 0) != DDI_SUCCESS) - return (DDI_FAILURE); - - if (ddi_create_minor_node(dip, LXA_MINORNAME_DSP, S_IFCHR, - LXA_MINORNUM_DSP, DDI_PSEUDO, 0) != DDI_SUCCESS) - return (DDI_FAILURE); - - if (ddi_create_minor_node(dip, LXA_MINORNAME_MIXER, S_IFCHR, - LXA_MINORNUM_MIXER, DDI_PSEUDO, 0) != DDI_SUCCESS) - return (DDI_FAILURE); - - /* allocate our data structures */ - lxa_minor_id = id_space_create("lxa_minor_id", - LXA_MINORNUM_COUNT, LX_AUDIO_MAX_OPENS); - lxa_state_hash = mod_hash_create_idhash("lxa_state_hash", - lxa_state_hash_size, mod_hash_null_valdtor); - lxa_zstate_hash = mod_hash_create_strhash("lxa_zstate_hash", - lxa_zstate_hash_size, mod_hash_null_valdtor); - - return (DDI_SUCCESS); -} - -static int -/*ARGSUSED*/ -lxa_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - if (cmd != DDI_DETACH) - return (DDI_FAILURE); - - ASSERT(!MUTEX_HELD(&lxa_lock)); - if (lxa_registered_zones > 0) - return (DDI_FAILURE); - - mod_hash_destroy_idhash(lxa_state_hash); - mod_hash_destroy_idhash(lxa_zstate_hash); - id_space_destroy(lxa_minor_id); - lxa_state_hash = NULL; - lxa_dip = NULL; - - return (DDI_SUCCESS); -} - -static int -/*ARGSUSED*/ -lxa_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **resultp) -{ - switch (infocmd) { - case DDI_INFO_DEVT2DEVINFO: - *resultp = lxa_dip; - return (DDI_SUCCESS); - - case DDI_INFO_DEVT2INSTANCE: - *resultp = (void *)0; - return (DDI_SUCCESS); - } - return (DDI_FAILURE); -} - -/* - * Driver flags - */ -static struct cb_ops lxa_cb_ops = { - lxa_open, /* open */ - lxa_close, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - lxa_read, /* read */ - lxa_write, /* write */ - lxa_ioctl, /* ioctl */ - lxa_devmap, /* devmap */ - nodev, /* mmap */ - ddi_devmap_segmap, /* segmap */ - nochpoll, /* chpoll */ - ddi_prop_op, /* prop_op */ - NULL, /* cb_str */ - D_NEW | D_MP | D_DEVMAP, - CB_REV, - NULL, - NULL -}; - -static struct dev_ops lxa_ops = { - DEVO_REV, - 0, - lxa_getinfo, - nulldev, - nulldev, - lxa_attach, - lxa_detach, - nodev, - &lxa_cb_ops, - NULL, - NULL, - ddi_quiesce_not_needed, /* quiesce */ -}; - -/* - * Module linkage information for the kernel. - */ -static struct modldrv modldrv = { - &mod_driverops, /* type of module */ - "linux audio driver", /* description of module */ - &lxa_ops /* driver ops */ -}; - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -/* - * standard module entry points - */ -int -_init(void) -{ - return (mod_install(&modlinkage)); -} - -int -_fini(void) -{ - return (mod_remove(&modlinkage)); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} diff --git a/usr/src/uts/common/brand/lx/io/lx_audio.conf b/usr/src/uts/common/brand/lx/io/lx_audio.conf deleted file mode 100644 index 2eeb5eb7ee..0000000000 --- a/usr/src/uts/common/brand/lx/io/lx_audio.conf +++ /dev/null @@ -1,27 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -name="lx_audio" parent="pseudo" instance=0; diff --git a/usr/src/uts/common/brand/lx/sys/lx_audio.h b/usr/src/uts/common/brand/lx/sys/lx_audio.h deleted file mode 100644 index cbb3431c4b..0000000000 --- a/usr/src/uts/common/brand/lx/sys/lx_audio.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _LX_AUDIO_H -#define _LX_AUDIO_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/zone.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * name for this driver - */ -#define LX_AUDIO_DRV "lx_audio" - -/* - * names for the minor nodes this driver exports - */ -#define LXA_MINORNAME_DEVCTL "lx_devctl" -#define LXA_MINORNAME_DSP "lx_dsp" -#define LXA_MINORNAME_MIXER "lx_mixer" - -/* - * minor numbers for the minor nodes this driver exporrts - */ -#define LXA_MINORNUM_DEVCTL 0 -#define LXA_MINORNUM_DSP 1 -#define LXA_MINORNUM_MIXER 2 -#define LXA_MINORNUM_COUNT 3 - -/* - * driver ioctls - * - * note that we're layering on top of solaris audio devices so we want - * to make sure that our ioctls namespace doesn't conflict with theirs. - * looking in sys/audioio.h and sys/mixer.h we see that they seem to - * use an _IO key of 'A' and 'M', so we'll choose an _IO key of 'a.' - */ - -/* - * administrative ioctls. - * these ioctls are only supported on the DEVCTL minor node - */ -#define LXA_IOC_ZONE_REG (_IOR('a', 0, lxa_zone_reg_t)) -#define LXA_IOC_ZONE_UNREG (_IOR('a', 1, lxa_zone_reg_t)) - - -/* - * audio and mixer device ioctls - * these ioctls are supported on DSP and MIXER minor nodes. - */ -#define LXA_IOC_GETMINORNUM (_IOR('a', 20, int)) - -/* - * audio device ioctls. - * these ioctls are supports on DSP minor nodes. - */ -#define LXA_IOC_MMAP_OUTPUT (_IOR('a', 41, int)) -#define LXA_IOC_MMAP_PTR (_IOR('a', 42, int)) -#define LXA_IOC_GET_FRAG_INFO (_IOR('a', 43, lxa_frag_info_t)) -#define LXA_IOC_SET_FRAG_INFO (_IOR('a', 44, lxa_frag_info_t)) - -/* - * mixer device ioctls. - * these ioctls are supports on MIXER minor nodes. - */ -#define LXA_IOC_MIXER_GET_VOL (_IOR('a', 60, lxa_mixer_levels_t)) -#define LXA_IOC_MIXER_SET_VOL (_IOR('a', 61, lxa_mixer_levels_t)) -#define LXA_IOC_MIXER_GET_MIC (_IOR('a', 62, lxa_mixer_levels_t)) -#define LXA_IOC_MIXER_SET_MIC (_IOR('a', 63, lxa_mixer_levels_t)) -#define LXA_IOC_MIXER_GET_PCM (_IOR('a', 64, lxa_mixer_levels_t)) -#define LXA_IOC_MIXER_SET_PCM (_IOR('a', 65, lxa_mixer_levels_t)) - -/* command structure for LXA_IOC_ZONE_REG */ -#define LXA_INTSTRLEN 32 -typedef struct lxa_zone_reg { - char lxa_zr_zone_name[ZONENAME_MAX]; - char lxa_zr_inputdev[LXA_INTSTRLEN]; - char lxa_zr_outputdev[LXA_INTSTRLEN]; -} lxa_zone_reg_t; - -/* command structure for LXA_IOC_GET_FRAG_INFO and LXA_IOC_SET_FRAG_INFO */ -typedef struct lxa_frag_info { - int lxa_fi_size; - int lxa_fi_cnt; -} lxa_frag_info_t; - -/* command structure for LXA_IOC_MIXER_GET_* and LXA_IOC_MIXER_SET_* */ -typedef struct lxa_mixer_levels { - int lxa_ml_gain; - int lxa_ml_balance; -} lxa_mixer_levels_t; - -/* verify that a solaris mixer level structure has valid values */ -#define LXA_MIXER_LEVELS_OK(x) (((x)->lxa_ml_gain >= AUDIO_MIN_GAIN) && \ - ((x)->lxa_ml_gain <= AUDIO_MAX_GAIN) && \ - ((x)->lxa_ml_balance >= AUDIO_LEFT_BALANCE) && \ - ((x)->lxa_ml_balance <= AUDIO_RIGHT_BALANCE)) - -#ifdef __cplusplus -} -#endif - -#endif /* _LX_AUDIO_H */ diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel index 78c2801cd2..6eb165e46f 100644 --- a/usr/src/uts/intel/Makefile.intel +++ b/usr/src/uts/intel/Makefile.intel @@ -527,7 +527,7 @@ MISC_KMODS += md_sp # Brand modules # BRAND_KMODS += sn1_brand s10_brand lx_brand -DRV_KMODS += lx_systrace lx_ptm lx_audio lx_netlink +DRV_KMODS += lx_systrace lx_ptm lx_netlink # # Exec Class Modules (/kernel/exec): diff --git a/usr/src/uts/intel/lx_audio/Makefile b/usr/src/uts/intel/lx_audio/Makefile deleted file mode 100644 index 9341fc7def..0000000000 --- a/usr/src/uts/intel/lx_audio/Makefile +++ /dev/null @@ -1,100 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# uts/intel/lx_audio/Makefile -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# This makefile drives the production of the lx_audio driver -# -# intel architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = lx_audio -OBJECTS = $(LX_AUDIO_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(LX_AUDIO_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(USR_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/brand/lx/io - -# -# Include common rules. -# -include $(UTSBASE)/intel/Makefile.intel - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -CPPFLAGS += -I$(UTSBASE)/common/brand/lx - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/intel/Makefile.targ - -$(OBJS_DIR)/%.o: $(UTSBASE)/common/brand/lx/io/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - -$(LINTS_DIR)/%.ln: $(UTSBASE)/common/brand/lx/io/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) |
