version 1.22.2.1, 2015/09/22 12:05:59 |
version 1.22.2.2, 2016/03/19 11:30:10 |
Line 43 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 43 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/vnode.h> |
#include <sys/vnode.h> |
#include <sys/module.h> |
#include <sys/module.h> |
#include <sys/atomic.h> |
#include <sys/atomic.h> |
|
#include <sys/time.h> |
|
|
#include <dev/audio_if.h> |
#include <dev/audio_if.h> |
#include <dev/audiovar.h> |
#include <dev/audiovar.h> |
Line 316 pad_open(dev_t dev, int flags, int fmt, |
|
Line 317 pad_open(dev_t dev, int flags, int fmt, |
|
if (atomic_swap_uint(&sc->sc_open, 1) != 0) { |
if (atomic_swap_uint(&sc->sc_open, 1) != 0) { |
return EBUSY; |
return EBUSY; |
} |
} |
|
|
|
getmicrotime(&sc->sc_last); |
|
sc->sc_bytes_count = 0; |
|
|
return 0; |
return 0; |
} |
} |
Line 335 pad_close(dev_t dev, int flags, int fmt, |
|
Line 339 pad_close(dev_t dev, int flags, int fmt, |
|
return 0; |
return 0; |
} |
} |
|
|
|
#define PAD_BYTES_PER_SEC (44100 * sizeof(int16_t) * 2) |
|
#define TIMENEXTREAD (20 * 1000) |
|
#define BYTESTOSLEEP (PAD_BYTES_PER_SEC / (1000000 / TIMENEXTREAD)) |
|
|
int |
int |
pad_read(dev_t dev, struct uio *uio, int flags) |
pad_read(dev_t dev, struct uio *uio, int flags) |
{ |
{ |
|
struct timeval now; |
|
uint64_t nowusec, lastusec; |
pad_softc_t *sc; |
pad_softc_t *sc; |
pad_block_t pb; |
pad_block_t pb; |
void (*intr)(void *); |
void (*intr)(void *); |
void *intrarg; |
void *intrarg; |
int err; |
int err, wait_ticks; |
|
|
sc = device_lookup_private(&pad_cd, PADUNIT(dev)); |
sc = device_lookup_private(&pad_cd, PADUNIT(dev)); |
if (sc == NULL) |
if (sc == NULL) |
Line 354 pad_read(dev_t dev, struct uio *uio, int |
|
Line 364 pad_read(dev_t dev, struct uio *uio, int |
|
intr = sc->sc_intr; |
intr = sc->sc_intr; |
intrarg = sc->sc_intrarg; |
intrarg = sc->sc_intrarg; |
|
|
kpreempt_disable(); |
|
while (uio->uio_resid > 0 && !err) { |
while (uio->uio_resid > 0 && !err) { |
|
getmicrotime(&now); |
|
nowusec = (now.tv_sec * 1000000) + now.tv_usec; |
|
lastusec = (sc->sc_last.tv_sec * 1000000) + |
|
sc->sc_last.tv_usec; |
|
if (lastusec + TIMENEXTREAD > nowusec && |
|
sc->sc_bytes_count >= BYTESTOSLEEP) { |
|
wait_ticks = (hz * ((lastusec + TIMENEXTREAD) - |
|
nowusec)) / 1000000; |
|
if (wait_ticks > 0) { |
|
kpause("padwait", TRUE, wait_ticks, |
|
&sc->sc_lock); |
|
} |
|
|
|
sc->sc_bytes_count -= BYTESTOSLEEP; |
|
getmicrotime(&sc->sc_last); |
|
} else if (sc->sc_bytes_count >= BYTESTOSLEEP) { |
|
sc->sc_bytes_count -= BYTESTOSLEEP; |
|
getmicrotime(&sc->sc_last); |
|
} else if (lastusec + TIMENEXTREAD <= nowusec) |
|
getmicrotime(&sc->sc_last); |
|
|
err = pad_get_block(sc, &pb, min(uio->uio_resid, PAD_BLKSIZE)); |
err = pad_get_block(sc, &pb, min(uio->uio_resid, PAD_BLKSIZE)); |
if (!err) { |
if (!err) { |
|
sc->sc_bytes_count += pb.pb_len; |
|
|
mutex_exit(&sc->sc_lock); |
mutex_exit(&sc->sc_lock); |
err = uiomove(pb.pb_ptr, pb.pb_len, uio); |
err = uiomove(pb.pb_ptr, pb.pb_len, uio); |
mutex_enter(&sc->sc_lock); |
mutex_enter(&sc->sc_lock); |
Line 366 pad_read(dev_t dev, struct uio *uio, int |
|
Line 398 pad_read(dev_t dev, struct uio *uio, int |
|
|
|
if (intr) { |
if (intr) { |
mutex_enter(&sc->sc_intr_lock); |
mutex_enter(&sc->sc_intr_lock); |
|
kpreempt_disable(); |
(*intr)(intrarg); |
(*intr)(intrarg); |
|
kpreempt_enable(); |
mutex_exit(&sc->sc_intr_lock); |
mutex_exit(&sc->sc_intr_lock); |
intr = sc->sc_intr; |
intr = sc->sc_intr; |
intrarg = sc->sc_intrarg; |
intrarg = sc->sc_intrarg; |
Line 374 pad_read(dev_t dev, struct uio *uio, int |
|
Line 408 pad_read(dev_t dev, struct uio *uio, int |
|
continue; |
continue; |
} |
} |
err = cv_wait_sig(&sc->sc_condvar, &sc->sc_lock); |
err = cv_wait_sig(&sc->sc_condvar, &sc->sc_lock); |
if (err != 0) { |
if (err != 0) |
mutex_exit(&sc->sc_lock); |
break; |
kpreempt_enable(); |
|
return err; |
|
} |
|
intr = sc->sc_intr; |
intr = sc->sc_intr; |
intrarg = sc->sc_intrarg; |
intrarg = sc->sc_intrarg; |
} |
} |
|
|
if (intr) { |
|
mutex_enter(&sc->sc_intr_lock); |
|
(*intr)(intrarg); |
|
mutex_exit(&sc->sc_intr_lock); |
|
} |
|
mutex_exit(&sc->sc_lock); |
mutex_exit(&sc->sc_lock); |
kpreempt_enable(); |
|
|
|
return err; |
return err; |
} |
} |