Deleted Added
full compact
31c31
< SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/mixer.c 170235 2007-06-03 10:56:22Z ariff $");
---
> SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/mixer.c 170815 2007-06-16 03:37:28Z ariff $");
38d37
< const char *type;
43a43
> int type;
85a86
> static d_ioctl_t mixer_ioctl;
89d89
< .d_flags = D_NEEDGIANT,
128a129,138
> #define MIXER_SET_UNLOCK(x, y) do { \
> if ((y) != 0) \
> snd_mtxunlock((x)->lock); \
> } while(0)
>
> #define MIXER_SET_LOCK(x, y) do { \
> if ((y) != 0) \
> snd_mtxlock((x)->lock); \
> } while(0)
>
130,131c140,141
< mixer_set_softpcmvol(struct snd_mixer *mixer, struct snddev_info *d,
< unsigned left, unsigned right)
---
> mixer_set_softpcmvol(struct snd_mixer *m, struct snddev_info *d,
> unsigned left, unsigned right)
134c144
< int locked;
---
> int dropmtx, acquiremtx;
136,139c146,147
< locked = (mixer->lock != NULL &&
< mtx_owned((struct mtx *)(mixer->lock))) ? 1 : 0;
< if (locked)
< snd_mtxunlock(mixer->lock);
---
> if (!PCM_REGISTERED(d))
> return (EINVAL);
140a149,168
> if (mtx_owned(m->lock))
> dropmtx = 1;
> else
> dropmtx = 0;
>
> if (!(d->flags & SD_F_MPSAFE) || mtx_owned(d->lock) != 0)
> acquiremtx = 0;
> else
> acquiremtx = 1;
>
> /*
> * Be careful here. If we're coming from cdev ioctl, it is OK to
> * not doing locking AT ALL (except on individual channel) since
> * we've been heavily guarded by pcm cv, or if we're still
> * under Giant influence. Since we also have mix_* calls, we cannot
> * assume such protection and just do the lock as usuall.
> */
> MIXER_SET_UNLOCK(m, dropmtx);
> MIXER_SET_LOCK(d, acquiremtx);
>
159,160c187,188
< if (locked)
< snd_mtxlock(mixer->lock);
---
> MIXER_SET_UNLOCK(d, acquiremtx);
> MIXER_SET_LOCK(m, dropmtx);
162c190
< return 0;
---
> return (0);
172c200
< int i;
---
> int i, dropmtx;
185a214,221
> /* It is safe to drop this mutex due to Giant. */
> if (!(d->flags & SD_F_MPSAFE) && mtx_owned(m->lock) != 0)
> dropmtx = 1;
> else
> dropmtx = 0;
>
> MIXER_SET_UNLOCK(m, dropmtx);
>
197c233
< mixer_set_softpcmvol(m, d, tl, tr);
---
> (void)mixer_set_softpcmvol(m, d, tl, tr);
199c235,236
< MIXER_SET(m, realdev, tl, tr) < 0)
---
> MIXER_SET(m, realdev, tl, tr) < 0) {
> MIXER_SET_LOCK(m, dropmtx);
200a238
> }
209c247
< mixer_set_softpcmvol(m, d, tl, tr);
---
> (void)mixer_set_softpcmvol(m, d, tl, tr);
215c253,254
< MIXER_SET(m, realdev, l, r) < 0)
---
> MIXER_SET(m, realdev, l, r) < 0) {
> MIXER_SET_LOCK(m, dropmtx);
216a256
> }
219c259
< mixer_set_softpcmvol(m, d, l, r);
---
> (void)mixer_set_softpcmvol(m, d, l, r);
221c261,262
< MIXER_SET(m, realdev, l, r) < 0)
---
> MIXER_SET(m, realdev, l, r) < 0) {
> MIXER_SET_LOCK(m, dropmtx);
222a264
> }
226a269,270
> MIXER_SET_LOCK(m, dropmtx);
>
235c279,280
< else return -1;
---
> else
> return -1;
240a286,295
> struct snddev_info *d;
> int dropmtx;
>
> d = device_get_softc(mixer->dev);
> if (d == NULL)
> return -1;
> if (!(d->flags & SD_F_MPSAFE) && mtx_owned(mixer->lock) != 0)
> dropmtx = 1;
> else
> dropmtx = 0;
243a299,300
> /* It is safe to drop this mutex due to Giant. */
> MIXER_SET_UNLOCK(mixer, dropmtx);
244a302
> MIXER_SET_LOCK(mixer, dropmtx);
485,486c543,545
< int
< mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
---
> static struct snd_mixer *
> mixer_obj_create(device_t dev, kobj_class_t cls, void *devinfo,
> int type, const char *desc)
488d546
< struct snddev_info *snddev;
490,492c548
< u_int16_t v;
< struct cdev *pdev;
< int i, unit, devunit, val;
---
> int i;
493a550,555
> KASSERT(dev != NULL && cls != NULL && devinfo != NULL,
> ("%s(): NULL data dev=%p cls=%p devinfo=%p",
> __func__, dev, cls, devinfo));
> KASSERT(type == MIXER_TYPE_PRIMARY || type == MIXER_TYPE_SECONDARY,
> ("invalid mixer type=%d", type));
>
495,497c557,565
< snprintf(m->name, MIXER_NAMELEN, "%s:mixer", device_get_nameunit(dev));
< m->lock = snd_mtxcreate(m->name, "pcm mixer");
< m->type = cls->name;
---
> snprintf(m->name, sizeof(m->name), "%s:mixer",
> device_get_nameunit(dev));
> if (desc != NULL) {
> strlcat(m->name, ":", sizeof(m->name));
> strlcat(m->name, desc, sizeof(m->name));
> }
> m->lock = snd_mtxcreate(m->name, (type == MIXER_TYPE_PRIMARY) ?
> "primary pcm mixer" : "secondary pcm mixer");
> m->type = type;
501c569
< for (i = 0; i < 32; i++) {
---
> for (i = 0; i < (sizeof(m->parent) / sizeof(m->parent[0])); i++) {
507,508c575,580
< if (MIXER_INIT(m))
< goto bad;
---
> if (MIXER_INIT(m)) {
> snd_mtxlock(m->lock);
> snd_mtxfree(m->lock);
> kobj_delete((kobj_t)m, M_MIXER);
> return (NULL);
> }
509a582,629
> return (m);
> }
>
> int
> mixer_delete(struct snd_mixer *m)
> {
> KASSERT(m != NULL, ("NULL snd_mixer"));
> KASSERT(m->type == MIXER_TYPE_SECONDARY,
> ("%s(): illegal mixer type=%d", __func__, m->type));
>
> snd_mtxlock(m->lock);
>
> MIXER_UNINIT(m);
>
> snd_mtxfree(m->lock);
> kobj_delete((kobj_t)m, M_MIXER);
>
> --mixer_count;
>
> return (0);
> }
>
> struct snd_mixer *
> mixer_create(device_t dev, kobj_class_t cls, void *devinfo, const char *desc)
> {
> struct snd_mixer *m;
>
> m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_SECONDARY, desc);
>
> if (m != NULL)
> ++mixer_count;
>
> return (m);
> }
>
> int
> mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
> {
> struct snddev_info *snddev;
> struct snd_mixer *m;
> u_int16_t v;
> struct cdev *pdev;
> int i, unit, devunit, val;
>
> m = mixer_obj_create(dev, cls, devinfo, MIXER_TYPE_PRIMARY, NULL);
> if (m == NULL)
> return (-1);
>
559,565c679
< return 0;
<
< bad:
< snd_mtxlock(m->lock);
< snd_mtxfree(m->lock);
< kobj_delete((kobj_t)m, M_MIXER);
< return -1;
---
> return (0);
579a694
>
580a696,699
> KASSERT(m != NULL, ("NULL snd_mixer"));
> KASSERT(m->type == MIXER_TYPE_PRIMARY,
> ("%s(): illegal mixer type=%d", __func__, m->type));
>
735a855,926
> int
> mixer_busy(struct snd_mixer *m)
> {
> KASSERT(m != NULL, ("NULL snd_mixer"));
>
> return (m->busy);
> }
>
> int
> mix_set(struct snd_mixer *m, u_int dev, u_int left, u_int right)
> {
> int ret;
>
> KASSERT(m != NULL, ("NULL snd_mixer"));
>
> snd_mtxlock(m->lock);
> ret = mixer_set(m, dev, left | (right << 8));
> snd_mtxunlock(m->lock);
>
> return ((ret != 0) ? ENXIO : 0);
> }
>
> int
> mix_get(struct snd_mixer *m, u_int dev)
> {
> int ret;
>
> KASSERT(m != NULL, ("NULL snd_mixer"));
>
> snd_mtxlock(m->lock);
> ret = mixer_get(m, dev);
> snd_mtxunlock(m->lock);
>
> return (ret);
> }
>
> int
> mix_setrecsrc(struct snd_mixer *m, u_int32_t src)
> {
> int ret;
>
> KASSERT(m != NULL, ("NULL snd_mixer"));
>
> snd_mtxlock(m->lock);
> ret = mixer_setrecsrc(m, src);
> snd_mtxunlock(m->lock);
>
> return ((ret != 0) ? ENXIO : 0);
> }
>
> u_int32_t
> mix_getrecsrc(struct snd_mixer *m)
> {
> u_int32_t ret;
>
> KASSERT(m != NULL, ("NULL snd_mixer"));
>
> snd_mtxlock(m->lock);
> ret = mixer_getrecsrc(m);
> snd_mtxunlock(m->lock);
>
> return (ret);
> }
>
> int
> mix_get_type(struct snd_mixer *m)
> {
> KASSERT(m != NULL, ("NULL snd_mixer"));
>
> return (m->type);
> }
>
740a932
> struct snddev_info *d;
742a935,938
>
> if (i_dev == NULL || i_dev->si_drv1 == NULL)
> return (EBADF);
>
744c940,942
< snd_mtxlock(m->lock);
---
> d = device_get_softc(m->dev);
> if (!PCM_REGISTERED(d))
> return (EBADF);
746c944
< m->busy = 1;
---
> /* XXX Need Giant magic entry ??? */
747a946,947
> snd_mtxlock(m->lock);
> m->busy = 1;
749c949,950
< return 0;
---
>
> return (0);
754a956
> struct snddev_info *d;
755a958
> int ret;
756a960,962
> if (i_dev == NULL || i_dev->si_drv1 == NULL)
> return (EBADF);
>
758c964,966
< snd_mtxlock(m->lock);
---
> d = device_get_softc(m->dev);
> if (!PCM_REGISTERED(d))
> return (EBADF);
760,764c968
< if (!m->busy) {
< snd_mtxunlock(m->lock);
< return EBADF;
< }
< m->busy = 0;
---
> /* XXX Need Giant magic entry ??? */
765a970,972
> snd_mtxlock(m->lock);
> ret = (m->busy == 0) ? EBADF : 0;
> m->busy = 0;
767c974,975
< return 0;
---
>
> return (ret);
769a978,1006
> static int
> mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
> struct thread *td)
> {
> struct snddev_info *d;
> int ret;
>
> if (i_dev == NULL || i_dev->si_drv1 == NULL)
> return (EBADF);
>
> d = device_get_softc(((struct snd_mixer *)i_dev->si_drv1)->dev);
> if (!PCM_REGISTERED(d))
> return (EBADF);
>
> PCM_GIANT_ENTER(d);
> PCM_ACQUIRE_QUICK(d);
>
> ret = mixer_ioctl_cmd(i_dev, cmd, arg, mode, td, MIXER_CMD_CDEV);
>
> PCM_RELEASE_QUICK(d);
> PCM_GIANT_LEAVE(d);
>
> return (ret);
> }
>
> /*
> * XXX Make sure you can guarantee concurrency safety before calling this
> * function, be it through Giant, PCM_CV_*, etc !
> */
771c1008,1009
< mixer_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td)
---
> mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
> struct thread *td, int from)
780c1018
< return EBADF;
---
> return (EBADF);
783c1021
< if (mode != -1 && !m->busy) {
---
> if (from == MIXER_CMD_CDEV && !m->busy) {
785c1023
< return EBADF;
---
> return (EBADF);
790c1028
< return mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg);
---
> return (mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg));
799c1037
< return (ret == 0)? 0 : ENXIO;
---
> return ((ret == 0) ? 0 : ENXIO);
823c1061
< return (v != -1)? 0 : ENXIO;
---
> return ((v != -1) ? 0 : ENXIO);
830a1069
> snd_mtxunlock(m->lock);
831a1071
> return (ret);
834c1074,1075
< ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg);
---
> snd_mtxunlock(m->lock);
> return (dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg));
849a1091
> break;
853c1095,1096
< return ret;
---
>
> return (ret);
870c1113
< if (d != NULL && d->mixer_dev != NULL) {
---
> if (PCM_REGISTERED(d) && d->mixer_dev != NULL) {
922,923c1165
< struct cdev *t_cdev;
< int nmix, ret, pcmunit, i;
---
> int nmix, i;
929,930c1171,1172
< if ((mi->dev == -1) && (i_dev->si_devsw != &mixer_cdevsw))
< return EINVAL;
---
> if (mi->dev == -1 && i_dev->si_devsw != &mixer_cdevsw)
> return (EINVAL);
934d1175
< t_cdev = NULL;
936,937d1176
< ret = 0;
< pcmunit = -1; /* pcmX */
946c1185
< if (d == NULL)
---
> if (!PCM_REGISTERED(d))
948a1188,1189
> /* XXX Need Giant magic entry */
>
951d1191
< pcm_inprog(d, 1);
954,961c1194,1198
< if (d->mixer_dev != NULL) {
< if (((mi->dev == -1) && (d->mixer_dev == i_dev)) || (mi->dev == nmix)) {
< t_cdev = d->mixer_dev;
< pcmunit = i;
< break;
< }
< ++nmix;
< }
---
> if (d->mixer_dev != NULL && d->mixer_dev->si_drv1 != NULL &&
> ((mi->dev == -1 && d->mixer_dev == i_dev) ||
> mi->dev == nmix)) {
> m = d->mixer_dev->si_drv1;
> mtx_lock(m->lock);
963,965c1200,1217
< pcm_unlock(d);
< pcm_inprog(d, -1);
< }
---
> /*
> * At this point, the following synchronization stuff
> * has happened:
> * - a specific PCM device is locked.
> * - a specific mixer device has been locked, so be
> * sure to unlock when existing.
> */
> bzero((void *)mi, sizeof(*mi));
> mi->dev = nmix;
> snprintf(mi->id, sizeof(mi->id), "mixer%d", i);
> strlcpy(mi->name, m->name, sizeof(mi->name));
> mi->modify_counter = m->modify_counter;
> mi->card_number = i;
> /*
> * Currently, FreeBSD assumes 1:1 relationship between
> * a pcm and mixer devices, so this is hardcoded to 0.
> */
> mi->port_number = 0;
967,972c1219,1228
< /*
< * If t_cdev is NULL, then search was exhausted and device wasn't
< * found. No locks are held, so just return.
< */
< if (t_cdev == NULL)
< return EINVAL;
---
> /**
> * @todo Fill in @sa oss_mixerinfo::mixerhandle.
> * @note From 4Front: "mixerhandle is an arbitrary
> * string that identifies the mixer better than
> * the device number (mixerinfo.dev). Device
> * numbers may change depending on the order the
> * drivers are loaded. However the handle should
> * remain the same provided that the sound card
> * is not moved to another PCI slot."
> */
974,975c1230,1239
< m = t_cdev->si_drv1;
< mtx_lock(m->lock);
---
> /**
> * @note
> * @sa oss_mixerinfo::magic is a reserved field.
> *
> * @par
> * From 4Front: "magic is usually 0. However some
> * devices may have dedicated setup utilities and the
> * magic field may contain an unique driver specific
> * value (managed by [4Front])."
> */
977,984c1241,1273
< /*
< * At this point, the following synchronization stuff has happened:
< * - a specific PCM device is locked and its "in progress
< * operations" counter has been incremented, so be sure to unlock
< * and decrement when exiting;
< * - a specific mixer device has been locked, so be sure to unlock
< * when existing.
< */
---
> mi->enabled = device_is_attached(m->dev) ? 1 : 0;
> /**
> * The only flag for @sa oss_mixerinfo::caps is
> * currently MIXER_CAP_VIRTUAL, which I'm not sure we
> * really worry about.
> */
> /**
> * Mixer extensions currently aren't supported, so
> * leave @sa oss_mixerinfo::nrext blank for now.
> */
> /**
> * @todo Fill in @sa oss_mixerinfo::priority (requires
> * touching drivers?)
> * @note The priority field is for mixer applets to
> * determine which mixer should be the default, with 0
> * being least preferred and 10 being most preferred.
> * From 4Front: "OSS drivers like ICH use higher
> * values (10) because such chips are known to be used
> * only on motherboards. Drivers for high end pro
> * devices use 0 because they will never be the
> * default mixer. Other devices use values 1 to 9
> * depending on the estimated probability of being the
> * default device.
> *
> * XXX Described by Hannu@4Front, but not found in
> * soundcard.h.
> strlcpy(mi->devnode, d->mixer_dev->si_name,
> sizeof(mi->devnode));
> mi->legacy_device = i;
> */
> mtx_unlock(m->lock);
> } else
> ++nmix;
986c1275
< bzero((void *)mi, sizeof(*mi));
---
> pcm_unlock(d);
988,997c1277,1279
< mi->dev = nmix;
< snprintf(mi->id, sizeof(mi->id), "mixer%d", dev2unit(t_cdev));
< strlcpy(mi->name, m->name, sizeof(mi->name));
< mi->modify_counter = m->modify_counter;
< mi->card_number = pcmunit;
< /*
< * Currently, FreeBSD assumes 1:1 relationship between a pcm and
< * mixer devices, so this is hardcoded to 0.
< */
< mi->port_number = 0;
---
> if (m != NULL)
> return (0);
> }
999,1049c1281
< /**
< * @todo Fill in @sa oss_mixerinfo::mixerhandle.
< * @note From 4Front: "mixerhandle is an arbitrary string that
< * identifies the mixer better than the device number
< * (mixerinfo.dev). Device numbers may change depending on
< * the order the drivers are loaded. However the handle
< * should remain the same provided that the sound card is
< * not moved to another PCI slot."
< */
<
< /**
< * @note
< * @sa oss_mixerinfo::magic is a reserved field.
< *
< * @par
< * From 4Front: "magic is usually 0. However some devices may have
< * dedicated setup utilities and the magic field may contain an
< * unique driver specific value (managed by [4Front])."
< */
<
< mi->enabled = device_is_attached(m->dev) ? 1 : 0;
< /**
< * The only flag for @sa oss_mixerinfo::caps is currently
< * MIXER_CAP_VIRTUAL, which I'm not sure we really worry about.
< */
< /**
< * Mixer extensions currently aren't supported, so leave
< * @sa oss_mixerinfo::nrext blank for now.
< */
< /**
< * @todo Fill in @sa oss_mixerinfo::priority (requires touching
< * drivers?)
< * @note The priority field is for mixer applets to determine which
< * mixer should be the default, with 0 being least preferred and 10
< * being most preferred. From 4Front: "OSS drivers like ICH use
< * higher values (10) because such chips are known to be used only
< * on motherboards. Drivers for high end pro devices use 0 because
< * they will never be the default mixer. Other devices use values 1
< * to 9 depending on the estimated probability of being the default
< * device.
< *
< * XXX Described by Hannu@4Front, but not found in soundcard.h.
< strlcpy(mi->devnode, t_cdev->si_name, sizeof(mi->devnode));
< mi->legacy_device = pcmunit;
< */
<
< mtx_unlock(m->lock);
< pcm_unlock(d);
< pcm_inprog(d, -1);
<
< return ret;
---
> return (EINVAL);