diff --git a/Makefile.target b/Makefile.target index a440bcb5b8..a65c55f371 100644 --- a/Makefile.target +++ b/Makefile.target @@ -36,6 +36,10 @@ endif PROGS=$(QEMU_PROG) $(QEMU_PROGW) STPFILES= +ifdef CONFIG_LINUX_USER +PROGS+=$(QEMU_PROG)-binfmt +endif + config-target.h: config-target.h-timestamp config-target.h-timestamp: config-target.mak @@ -115,6 +119,8 @@ QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) \ obj-y += linux-user/ obj-y += gdbstub.o thunk.o user-exec.o +obj-binfmt-y += linux-user/ + endif #CONFIG_LINUX_USER ######################################################### @@ -163,7 +169,11 @@ endif # CONFIG_SOFTMMU # Workaround for http://gcc.gnu.org/PR55489, see configure. %/translate.o: QEMU_CFLAGS += $(TRANSLATE_OPT_CFLAGS) +ifdef CONFIG_LINUX_USER +dummy := $(call unnest-vars,,obj-y obj-binfmt-y) +else dummy := $(call unnest-vars,,obj-y) +endif all-obj-y := $(obj-y) target-obj-y := @@ -200,6 +210,9 @@ ifdef CONFIG_DARWIN $(call quiet-command,SetFile -a C $@," SETFILE $(TARGET_DIR)$@") endif +$(QEMU_PROG)-binfmt: $(obj-binfmt-y) + $(call LINK,$^) + gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@") diff --git a/block/Makefile.objs b/block/Makefile.objs index 2593a2f8a6..f049d53077 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -21,6 +21,8 @@ block-obj-$(CONFIG_GLUSTERFS) += gluster.o block-obj-$(CONFIG_ARCHIPELAGO) += archipelago.o block-obj-$(CONFIG_LIBSSH2) += ssh.o block-obj-y += accounting.o dirty-bitmap.o +block-obj-y += dictzip.o +block-obj-y += tar.o block-obj-y += write-threshold.o block-obj-y += crypto.o diff --git a/block/dictzip.c b/block/dictzip.c new file mode 100644 index 0000000000..3235337164 --- /dev/null +++ b/block/dictzip.c @@ -0,0 +1,586 @@ +/* + * DictZip Block driver for dictzip enabled gzip files + * + * Use the "dictzip" tool from the "dictd" package to create gzip files that + * contain the extra DictZip headers. + * + * dictzip(1) is a compression program which creates compressed files in the + * gzip format (see RFC 1952). However, unlike gzip(1), dictzip(1) compresses + * the file in pieces and stores an index to the pieces in the gzip header. + * This allows random access to the file at the granularity of the compressed + * pieces (currently about 64kB) while maintaining good compression ratios + * (within 5% of the expected ratio for dictionary data). + * dictd(8) uses files stored in this format. + * + * For details on DictZip see http://dict.org/. + * + * Copyright (c) 2009 Alexander Graf + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "block/block_int.h" +#include + +// #define DEBUG + +#ifdef DEBUG +#define dprintf(fmt, ...) do { printf("dzip: " fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) do { } while (0) +#endif + +#define SECTOR_SIZE 512 +#define Z_STREAM_COUNT 4 +#define CACHE_COUNT 20 + +/* magic values */ + +#define GZ_MAGIC1 0x1f +#define GZ_MAGIC2 0x8b +#define DZ_MAGIC1 'R' +#define DZ_MAGIC2 'A' + +#define GZ_FEXTRA 0x04 /* Optional field (random access index) */ +#define GZ_FNAME 0x08 /* Original name */ +#define GZ_COMMENT 0x10 /* Zero-terminated, human-readable comment */ +#define GZ_FHCRC 0x02 /* Header CRC16 */ + +/* offsets */ + +#define GZ_ID 0 /* GZ_MAGIC (16bit) */ +#define GZ_FLG 3 /* FLaGs (see above) */ +#define GZ_XLEN 10 /* eXtra LENgth (16bit) */ +#define GZ_SI 12 /* Subfield ID (16bit) */ +#define GZ_VERSION 16 /* Version for subfield format */ +#define GZ_CHUNKSIZE 18 /* Chunk size (16bit) */ +#define GZ_CHUNKCNT 20 /* Number of chunks (16bit) */ +#define GZ_RNDDATA 22 /* Random access data (16bit) */ + +#define GZ_99_CHUNKSIZE 18 /* Chunk size (32bit) */ +#define GZ_99_CHUNKCNT 22 /* Number of chunks (32bit) */ +#define GZ_99_FILESIZE 26 /* Size of unpacked file (64bit) */ +#define GZ_99_RNDDATA 34 /* Random access data (32bit) */ + +struct BDRVDictZipState; + +typedef struct DictZipAIOCB { + BlockAIOCB common; + struct BDRVDictZipState *s; + QEMUIOVector *qiov; /* QIOV of the original request */ + QEMUIOVector *qiov_gz; /* QIOV of the gz subrequest */ + QEMUBH *bh; /* BH for cache */ + z_stream *zStream; /* stream to use for decoding */ + int zStream_id; /* stream id of the above pointer */ + size_t start; /* offset into the uncompressed file */ + size_t len; /* uncompressed bytes to read */ + uint8_t *gzipped; /* the gzipped data */ + uint8_t *buf; /* cached result */ + size_t gz_len; /* amount of gzip data */ + size_t gz_start; /* uncompressed starting point of gzip data */ + uint64_t offset; /* offset for "start" into the uncompressed chunk */ + int chunks_len; /* amount of uncompressed data in all gzip data */ +} DictZipAIOCB; + +typedef struct dict_cache { + size_t start; + size_t len; + uint8_t *buf; +} DictCache; + +typedef struct BDRVDictZipState { + BlockDriverState *hd; + z_stream zStream[Z_STREAM_COUNT]; + DictCache cache[CACHE_COUNT]; + int cache_index; + uint8_t stream_in_use; + uint64_t chunk_len; + uint32_t chunk_cnt; + uint16_t *chunks; + uint32_t *chunks32; + uint64_t *offsets; + int64_t file_len; +} BDRVDictZipState; + +static int start_zStream(z_stream *zStream) +{ + zStream->zalloc = NULL; + zStream->zfree = NULL; + zStream->opaque = NULL; + zStream->next_in = 0; + zStream->avail_in = 0; + zStream->next_out = NULL; + zStream->avail_out = 0; + + return inflateInit2( zStream, -15 ); +} + +static QemuOptsList runtime_opts = { + .name = "dzip", + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), + .desc = { + { + .name = "filename", + .type = QEMU_OPT_STRING, + .help = "URL to the dictzip file", + }, + { /* end of list */ } + }, +}; + +static int dictzip_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) +{ + BDRVDictZipState *s = bs->opaque; + const char *err = "Unknown (read error?)"; + uint8_t magic[2]; + char buf[100]; + uint8_t header_flags; + uint16_t chunk_len16; + uint16_t chunk_cnt16; + uint32_t chunk_len32; + uint16_t header_ver; + uint16_t tmp_short; + uint64_t offset; + int chunks_len; + int headerLength = GZ_XLEN - 1; + int rnd_offs; + int ret; + int i; + QemuOpts *opts; + Error *local_err = NULL; + const char *filename; + + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } + + filename = qemu_opt_get(opts, "filename"); + + if (!strncmp(filename, "dzip://", 7)) + filename += 7; + else if (!strncmp(filename, "dzip:", 5)) + filename += 5; + + s->hd = bdrv_open(filename, NULL, NULL, flags | BDRV_O_PROTOCOL, errp); + if (!s->hd) { + ret = -EINVAL; + qemu_opts_del(opts); + return ret; + } + + /* initialize zlib streams */ + for (i = 0; i < Z_STREAM_COUNT; i++) { + if (start_zStream( &s->zStream[i] ) != Z_OK) { + err = s->zStream[i].msg; + goto fail; + } + } + + /* gzip header */ + if (bdrv_pread(s->hd->file, GZ_ID, &magic, sizeof(magic)) != sizeof(magic)) + goto fail; + + if (!((magic[0] == GZ_MAGIC1) && (magic[1] == GZ_MAGIC2))) { + err = "No gzip file"; + goto fail; + } + + /* dzip header */ + if (bdrv_pread(s->hd->file, GZ_FLG, &header_flags, 1) != 1) + goto fail; + + if (!(header_flags & GZ_FEXTRA)) { + err = "Not a dictzip file (wrong flags)"; + goto fail; + } + + /* extra length */ + if (bdrv_pread(s->hd->file, GZ_XLEN, &tmp_short, 2) != 2) + goto fail; + + headerLength += le16_to_cpu(tmp_short) + 2; + + /* DictZip magic */ + if (bdrv_pread(s->hd->file, GZ_SI, &magic, 2) != 2) + goto fail; + + if (magic[0] != DZ_MAGIC1 || magic[1] != DZ_MAGIC2) { + err = "Not a dictzip file (missing extra magic)"; + goto fail; + } + + /* DictZip version */ + if (bdrv_pread(s->hd->file, GZ_VERSION, &header_ver, 2) != 2) + goto fail; + + header_ver = le16_to_cpu(header_ver); + + switch (header_ver) { + case 1: /* Normal DictZip */ + /* number of chunks */ + if (bdrv_pread(s->hd->file, GZ_CHUNKSIZE, &chunk_len16, 2) != 2) + goto fail; + + s->chunk_len = le16_to_cpu(chunk_len16); + + /* chunk count */ + if (bdrv_pread(s->hd->file, GZ_CHUNKCNT, &chunk_cnt16, 2) != 2) + goto fail; + + s->chunk_cnt = le16_to_cpu(chunk_cnt16); + chunks_len = sizeof(short) * s->chunk_cnt; + rnd_offs = GZ_RNDDATA; + break; + case 99: /* Special Alex pigz version */ + /* number of chunks */ + if (bdrv_pread(s->hd->file, GZ_99_CHUNKSIZE, &chunk_len32, 4) != 4) + goto fail; + + dprintf("chunk len [%#x] = %d\n", GZ_99_CHUNKSIZE, chunk_len32); + s->chunk_len = le32_to_cpu(chunk_len32); + + /* chunk count */ + if (bdrv_pread(s->hd->file, GZ_99_CHUNKCNT, &s->chunk_cnt, 4) != 4) + goto fail; + + s->chunk_cnt = le32_to_cpu(s->chunk_cnt); + + dprintf("chunk len | count = %"PRId64" | %d\n", s->chunk_len, s->chunk_cnt); + + /* file size */ + if (bdrv_pread(s->hd->file, GZ_99_FILESIZE, &s->file_len, 8) != 8) + goto fail; + + s->file_len = le64_to_cpu(s->file_len); + chunks_len = sizeof(int) * s->chunk_cnt; + rnd_offs = GZ_99_RNDDATA; + break; + default: + err = "Invalid DictZip version"; + goto fail; + } + + /* random access data */ + s->chunks = g_malloc(chunks_len); + if (header_ver == 99) + s->chunks32 = (uint32_t *)s->chunks; + + if (bdrv_pread(s->hd->file, rnd_offs, s->chunks, chunks_len) != chunks_len) + goto fail; + + /* orig filename */ + if (header_flags & GZ_FNAME) { + if (bdrv_pread(s->hd->file, headerLength + 1, buf, sizeof(buf)) != sizeof(buf)) + goto fail; + + buf[sizeof(buf) - 1] = '\0'; + headerLength += strlen(buf) + 1; + + if (strlen(buf) == sizeof(buf)) + goto fail; + + dprintf("filename: %s\n", buf); + } + + /* comment field */ + if (header_flags & GZ_COMMENT) { + if (bdrv_pread(s->hd->file, headerLength, buf, sizeof(buf)) != sizeof(buf)) + goto fail; + + buf[sizeof(buf) - 1] = '\0'; + headerLength += strlen(buf) + 1; + + if (strlen(buf) == sizeof(buf)) + goto fail; + + dprintf("comment: %s\n", buf); + } + + if (header_flags & GZ_FHCRC) + headerLength += 2; + + /* uncompressed file length*/ + if (!s->file_len) { + uint32_t file_len; + + if (bdrv_pread(s->hd->file, bdrv_getlength(s->hd) - 4, &file_len, 4) != 4) + goto fail; + + s->file_len = le32_to_cpu(file_len); + } + + /* compute offsets */ + s->offsets = g_malloc(sizeof( *s->offsets ) * s->chunk_cnt); + + for (offset = headerLength + 1, i = 0; i < s->chunk_cnt; i++) { + s->offsets[i] = offset; + switch (header_ver) { + case 1: + offset += le16_to_cpu(s->chunks[i]); + break; + case 99: + offset += le32_to_cpu(s->chunks32[i]); + break; + } + + dprintf("chunk %#"PRIx64" - %#"PRIx64" = offset %#"PRIx64" -> %#"PRIx64"\n", i * s->chunk_len, (i+1) * s->chunk_len, s->offsets[i], offset); + } + qemu_opts_del(opts); + + return 0; + +fail: + fprintf(stderr, "DictZip: Error opening file: %s\n", err); + bdrv_unref(s->hd); + if (s->chunks) + g_free(s->chunks); + qemu_opts_del(opts); + return -EINVAL; +} + +/* This callback gets invoked when we have the result in cache already */ +static void dictzip_cache_cb(void *opaque) +{ + DictZipAIOCB *acb = (DictZipAIOCB *)opaque; + + qemu_iovec_from_buf(acb->qiov, 0, acb->buf, acb->len); + acb->common.cb(acb->common.opaque, 0); + qemu_bh_delete(acb->bh); + qemu_aio_unref(acb); +} + +/* This callback gets invoked by the underlying block reader when we have + * all compressed data. We uncompress in here. */ +static void dictzip_read_cb(void *opaque, int ret) +{ + DictZipAIOCB *acb = (DictZipAIOCB *)opaque; + struct BDRVDictZipState *s = acb->s; + uint8_t *buf; + DictCache *cache; + int r, i; + + buf = g_malloc(acb->chunks_len); + + /* try to find zlib stream for decoding */ + do { + for (i = 0; i < Z_STREAM_COUNT; i++) { + if (!(s->stream_in_use & (1 << i))) { + s->stream_in_use |= (1 << i); + acb->zStream_id = i; + acb->zStream = &s->zStream[i]; + break; + } + } + } while(!acb->zStream); + + /* sure, we could handle more streams, but this callback should be single + threaded and when it's not, we really want to know! */ + assert(i == 0); + + /* uncompress the chunk */ + acb->zStream->next_in = acb->gzipped; + acb->zStream->avail_in = acb->gz_len; + acb->zStream->next_out = buf; + acb->zStream->avail_out = acb->chunks_len; + + r = inflate( acb->zStream, Z_PARTIAL_FLUSH ); + if ( (r != Z_OK) && (r != Z_STREAM_END) ) + fprintf(stderr, "Error inflating: [%d] %s\n", r, acb->zStream->msg); + + if ( r == Z_STREAM_END ) + inflateReset(acb->zStream); + + dprintf("inflating [%d] left: %d | %d bytes\n", r, acb->zStream->avail_in, acb->zStream->avail_out); + s->stream_in_use &= ~(1 << acb->zStream_id); + + /* nofity the caller */ + qemu_iovec_from_buf(acb->qiov, 0, buf + acb->offset, acb->len); + acb->common.cb(acb->common.opaque, 0); + + /* fill the cache */ + cache = &s->cache[s->cache_index]; + s->cache_index++; + if (s->cache_index == CACHE_COUNT) + s->cache_index = 0; + + cache->len = 0; + if (cache->buf) + g_free(cache->buf); + cache->start = acb->gz_start; + cache->buf = buf; + cache->len = acb->chunks_len; + + /* free occupied ressources */ + g_free(acb->qiov_gz); + qemu_aio_unref(acb); +} + +static const AIOCBInfo dictzip_aiocb_info = { + .aiocb_size = sizeof(DictZipAIOCB), +}; + +/* This is where we get a request from a caller to read something */ +static BlockAIOCB *dictzip_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) +{ + BDRVDictZipState *s = bs->opaque; + DictZipAIOCB *acb; + QEMUIOVector *qiov_gz; + struct iovec *iov; + uint8_t *buf; + size_t start = sector_num * SECTOR_SIZE; + size_t len = nb_sectors * SECTOR_SIZE; + size_t end = start + len; + size_t gz_start; + size_t gz_len; + int64_t gz_sector_num; + int gz_nb_sectors; + int first_chunk, last_chunk; + int first_offset; + int i; + + acb = qemu_aio_get(&dictzip_aiocb_info, bs, cb, opaque); + if (!acb) + return NULL; + + /* Search Cache */ + for (i = 0; i < CACHE_COUNT; i++) { + if (!s->cache[i].len) + continue; + + if ((start >= s->cache[i].start) && + (end <= (s->cache[i].start + s->cache[i].len))) { + acb->buf = s->cache[i].buf + (start - s->cache[i].start); + acb->len = len; + acb->qiov = qiov; + acb->bh = qemu_bh_new(dictzip_cache_cb, acb); + qemu_bh_schedule(acb->bh); + + return &acb->common; + } + } + + /* No cache, so let's decode */ + /* We need to read these chunks */ + first_chunk = start / s->chunk_len; + first_offset = start - first_chunk * s->chunk_len; + last_chunk = end / s->chunk_len; + + gz_start = s->offsets[first_chunk]; + gz_len = 0; + for (i = first_chunk; i <= last_chunk; i++) { + if (s->chunks32) + gz_len += le32_to_cpu(s->chunks32[i]); + else + gz_len += le16_to_cpu(s->chunks[i]); + } + + gz_sector_num = gz_start / SECTOR_SIZE; + gz_nb_sectors = (gz_len / SECTOR_SIZE); + + /* account for tail and heads */ + while ((gz_start + gz_len) > ((gz_sector_num + gz_nb_sectors) * SECTOR_SIZE)) + gz_nb_sectors++; + + /* Allocate qiov, iov and buf in one chunk so we only need to free qiov */ + qiov_gz = g_malloc0(sizeof(QEMUIOVector) + sizeof(struct iovec) + + (gz_nb_sectors * SECTOR_SIZE)); + iov = (struct iovec *)(((char *)qiov_gz) + sizeof(QEMUIOVector)); + buf = ((uint8_t *)iov) + sizeof(struct iovec *); + + /* Kick off the read by the backing file, so we can start decompressing */ + iov->iov_base = (void *)buf; + iov->iov_len = gz_nb_sectors * 512; + qemu_iovec_init_external(qiov_gz, iov, 1); + + dprintf("read %zd - %zd => %zd - %zd\n", start, end, gz_start, gz_start + gz_len); + + acb->s = s; + acb->qiov = qiov; + acb->qiov_gz = qiov_gz; + acb->start = start; + acb->len = len; + acb->gzipped = buf + (gz_start % SECTOR_SIZE); + acb->gz_len = gz_len; + acb->gz_start = first_chunk * s->chunk_len; + acb->offset = first_offset; + acb->chunks_len = (last_chunk - first_chunk + 1) * s->chunk_len; + + return bdrv_aio_readv(s->hd->file, gz_sector_num, qiov_gz, gz_nb_sectors, + dictzip_read_cb, acb); +} + +static void dictzip_close(BlockDriverState *bs) +{ + BDRVDictZipState *s = bs->opaque; + int i; + + for (i = 0; i < CACHE_COUNT; i++) { + if (!s->cache[i].len) + continue; + + g_free(s->cache[i].buf); + } + + for (i = 0; i < Z_STREAM_COUNT; i++) { + inflateEnd(&s->zStream[i]); + } + + if (s->chunks) + g_free(s->chunks); + + if (s->offsets) + g_free(s->offsets); + + dprintf("Close\n"); +} + +static int64_t dictzip_getlength(BlockDriverState *bs) +{ + BDRVDictZipState *s = bs->opaque; + dprintf("getlength -> %ld\n", s->file_len); + return s->file_len; +} + +static BlockDriver bdrv_dictzip = { + .format_name = "dzip", + .protocol_name = "dzip", + + .instance_size = sizeof(BDRVDictZipState), + .bdrv_file_open = dictzip_open, + .bdrv_close = dictzip_close, + .bdrv_getlength = dictzip_getlength, + + .bdrv_aio_readv = dictzip_aio_readv, +}; + +static void dictzip_block_init(void) +{ + bdrv_register(&bdrv_dictzip); +} + +block_init(dictzip_block_init); diff --git a/block/tar.c b/block/tar.c new file mode 100644 index 0000000000..734082a011 --- /dev/null +++ b/block/tar.c @@ -0,0 +1,379 @@ +/* + * Tar block driver + * + * Copyright (c) 2009 Alexander Graf + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "block/block_int.h" + +// #define DEBUG + +#ifdef DEBUG +#define dprintf(fmt, ...) do { printf("tar: " fmt, ## __VA_ARGS__); } while (0) +#else +#define dprintf(fmt, ...) do { } while (0) +#endif + +#define SECTOR_SIZE 512 + +#define POSIX_TAR_MAGIC "ustar" +#define OFFS_LENGTH 0x7c +#define OFFS_TYPE 0x9c +#define OFFS_MAGIC 0x101 + +#define OFFS_S_SP 0x182 +#define OFFS_S_EXT 0x1e2 +#define OFFS_S_LENGTH 0x1e3 +#define OFFS_SX_EXT 0x1f8 + +typedef struct SparseCache { + uint64_t start; + uint64_t end; +} SparseCache; + +typedef struct BDRVTarState { + BlockDriverState *hd; + size_t file_sec; + uint64_t file_len; + SparseCache *sparse; + int sparse_num; + uint64_t last_end; + char longfile[2048]; +} BDRVTarState; + +static int str_ends(char *str, const char *end) +{ + int end_len = strlen(end); + int str_len = strlen(str); + + if (str_len < end_len) + return 0; + + return !strncmp(str + str_len - end_len, end, end_len); +} + +static int is_target_file(BlockDriverState *bs, char *filename, + char *header) +{ + int retval = 0; + + if (str_ends(filename, ".raw")) + retval = 1; + + if (str_ends(filename, ".qcow")) + retval = 1; + + if (str_ends(filename, ".qcow2")) + retval = 1; + + if (str_ends(filename, ".vmdk")) + retval = 1; + + if (retval && + (header[OFFS_TYPE] != '0') && + (header[OFFS_TYPE] != 'S')) { + retval = 0; + } + + dprintf("does filename %s match? %s\n", filename, retval ? "yes" : "no"); + + /* make sure we're not using this name again */ + filename[0] = '\0'; + + return retval; +} + +static uint64_t tar2u64(char *ptr) +{ + uint64_t retval; + char oldend = ptr[12]; + + ptr[12] = '\0'; + if (*ptr & 0x80) { + /* XXX we only support files up to 64 bit length */ + retval = be64_to_cpu(*(uint64_t *)(ptr+4)); + dprintf("Convert %lx -> %#lx\n", *(uint64_t*)(ptr+4), retval); + } else { + retval = strtol(ptr, NULL, 8); + dprintf("Convert %s -> %#lx\n", ptr, retval); + } + + ptr[12] = oldend; + + return retval; +} + +static void tar_sparse(BDRVTarState *s, uint64_t offs, uint64_t len) +{ + SparseCache *sparse; + + if (!len) + return; + if (!(offs - s->last_end)) { + s->last_end += len; + return; + } + if (s->last_end > offs) + return; + + dprintf("Last chunk until %lx new chunk at %lx\n", s->last_end, offs); + + s->sparse = g_realloc(s->sparse, (s->sparse_num + 1) * sizeof(SparseCache)); + sparse = &s->sparse[s->sparse_num]; + sparse->start = s->last_end; + sparse->end = offs; + s->last_end = offs + len; + s->sparse_num++; + dprintf("Sparse at %lx end=%lx\n", sparse->start, + sparse->end); +} + +static QemuOptsList runtime_opts = { + .name = "tar", + .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head), + .desc = { + { + .name = "filename", + .type = QEMU_OPT_STRING, + .help = "URL to the tar file", + }, + { /* end of list */ } + }, +}; + +static int tar_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) +{ + BDRVTarState *s = bs->opaque; + char header[SECTOR_SIZE]; + char *real_file = header; + char *magic; + size_t header_offs = 0; + int ret; + QemuOpts *opts; + Error *local_err = NULL; + const char *filename; + + opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); + qemu_opts_absorb_qdict(opts, options, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + ret = -EINVAL; + goto fail; + } + + filename = qemu_opt_get(opts, "filename"); + + if (!strncmp(filename, "tar://", 6)) + filename += 6; + else if (!strncmp(filename, "tar:", 4)) + filename += 4; + + s->hd = bdrv_open(filename, NULL, NULL, flags | BDRV_O_PROTOCOL, errp); + if (!s->hd) { + ret = -EINVAL; + qemu_opts_del(opts); + return ret; + } + + /* Search the file for an image */ + + do { + /* tar header */ + if (bdrv_pread(s->hd->file, header_offs, header, SECTOR_SIZE) != SECTOR_SIZE) + goto fail; + + if ((header_offs > 1) && !header[0]) { + fprintf(stderr, "Tar: No image file found in archive\n"); + goto fail; + } + + magic = &header[OFFS_MAGIC]; + if (strncmp(magic, POSIX_TAR_MAGIC, 5)) { + fprintf(stderr, "Tar: Invalid magic: %s\n", magic); + goto fail; + } + + dprintf("file type: %c\n", header[OFFS_TYPE]); + + /* file length*/ + s->file_len = (tar2u64(&header[OFFS_LENGTH]) + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + s->file_sec = (header_offs / SECTOR_SIZE) + 1; + + header_offs += s->file_len + SECTOR_SIZE; + + if (header[OFFS_TYPE] == 'L') { + bdrv_pread(s->hd->file, header_offs - s->file_len, s->longfile, + sizeof(s->longfile)); + s->longfile[sizeof(s->longfile)-1] = '\0'; + real_file = header; + } else if (s->longfile[0]) { + real_file = s->longfile; + } else { + real_file = header; + } + } while(!is_target_file(bs, real_file, header)); + + /* We found an image! */ + + if (header[OFFS_TYPE] == 'S') { + uint8_t isextended; + int i; + + for (i = OFFS_S_SP; i < (OFFS_S_SP + (4 * 24)); i += 24) + tar_sparse(s, tar2u64(&header[i]), tar2u64(&header[i+12])); + + s->file_len = tar2u64(&header[OFFS_S_LENGTH]); + isextended = header[OFFS_S_EXT]; + + while (isextended) { + if (bdrv_pread(s->hd->file, s->file_sec * SECTOR_SIZE, header, + SECTOR_SIZE) != SECTOR_SIZE) + goto fail; + + for (i = 0; i < (21 * 24); i += 24) + tar_sparse(s, tar2u64(&header[i]), tar2u64(&header[i+12])); + isextended = header[OFFS_SX_EXT]; + s->file_sec++; + } + tar_sparse(s, s->file_len, 1); + } + qemu_opts_del(opts); + + return 0; + +fail: + fprintf(stderr, "Tar: Error opening file\n"); + bdrv_unref(s->hd); + qemu_opts_del(opts); + return -EINVAL; +} + +typedef struct TarAIOCB { + BlockAIOCB common; + QEMUBH *bh; +} TarAIOCB; + +/* This callback gets invoked when we have pure sparseness */ +static void tar_sparse_cb(void *opaque) +{ + TarAIOCB *acb = (TarAIOCB *)opaque; + + acb->common.cb(acb->common.opaque, 0); + qemu_bh_delete(acb->bh); + qemu_aio_unref(acb); +} + +static AIOCBInfo tar_aiocb_info = { + .aiocb_size = sizeof(TarAIOCB), +}; + +/* This is where we get a request from a caller to read something */ +static BlockAIOCB *tar_aio_readv(BlockDriverState *bs, + int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque) +{ + BDRVTarState *s = bs->opaque; + SparseCache *sparse; + int64_t sec_file = sector_num + s->file_sec; + int64_t start = sector_num * SECTOR_SIZE; + int64_t end = start + (nb_sectors * SECTOR_SIZE); + int i; + TarAIOCB *acb; + + for (i = 0; i < s->sparse_num; i++) { + sparse = &s->sparse[i]; + if (sparse->start > end) { + /* We expect the cache to be start increasing */ + break; + } else if ((sparse->start < start) && (sparse->end <= start)) { + /* sparse before our offset */ + sec_file -= (sparse->end - sparse->start) / SECTOR_SIZE; + } else if ((sparse->start <= start) && (sparse->end >= end)) { + /* all our sectors are sparse */ + char *buf = g_malloc0(nb_sectors * SECTOR_SIZE); + + acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque); + qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE); + g_free(buf); + acb->bh = qemu_bh_new(tar_sparse_cb, acb); + qemu_bh_schedule(acb->bh); + + return &acb->common; + } else if (((sparse->start >= start) && (sparse->start < end)) || + ((sparse->end >= start) && (sparse->end < end))) { + /* we're semi-sparse (worst case) */ + /* let's go synchronous and read all sectors individually */ + char *buf = g_malloc(nb_sectors * SECTOR_SIZE); + uint64_t offs; + + for (offs = 0; offs < (nb_sectors * SECTOR_SIZE); + offs += SECTOR_SIZE) { + bdrv_pread(bs->file, (sector_num * SECTOR_SIZE) + offs, + buf + offs, SECTOR_SIZE); + } + + qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE); + acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque); + acb->bh = qemu_bh_new(tar_sparse_cb, acb); + qemu_bh_schedule(acb->bh); + + return &acb->common; + } + } + + return bdrv_aio_readv(s->hd->file, sec_file, qiov, nb_sectors, + cb, opaque); +} + +static void tar_close(BlockDriverState *bs) +{ + dprintf("Close\n"); +} + +static int64_t tar_getlength(BlockDriverState *bs) +{ + BDRVTarState *s = bs->opaque; + dprintf("getlength -> %ld\n", s->file_len); + return s->file_len; +} + +static BlockDriver bdrv_tar = { + .format_name = "tar", + .protocol_name = "tar", + + .instance_size = sizeof(BDRVTarState), + .bdrv_file_open = tar_open, + .bdrv_close = tar_close, + .bdrv_getlength = tar_getlength, + + .bdrv_aio_readv = tar_aio_readv, +}; + +static void tar_block_init(void) +{ + bdrv_register(&bdrv_tar); +} + +block_init(tar_block_init); diff --git a/configure b/configure index f57fcc689d..7a57435307 100755 --- a/configure +++ b/configure @@ -1545,7 +1545,7 @@ fi if test "$pie" = ""; then case "$cpu-$targetos" in - i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD) + i386-Linux|x86_64-Linux|x32-Linux|ppc*-Linux|i386-OpenBSD|x86_64-OpenBSD) ;; *) pie="no" @@ -4049,6 +4049,33 @@ if test "$usb_redir" != "no" ; then fi fi +if test "$linux_user" = "no" -a "$cpu" = "ppc" -a "$targetos" = "Linux" ; then + # Do we need libm + cat > $TMPC << EOF + #include + #include + #include + int64_t val; + int main(int argc, char **argv) + { + val = (int64_t)read(0, NULL, 0); + if (atomic_read(&val) == -1) { + return 0; + } + return 1; + } +EOF + if compile_prog "-Iinclude" "" ; then + : + echo "No need to link with -latomic on powerpc-linux" + elif compile_prog "-Iinclude" "-latomic" ; then + echo "Link with -latomic on powerpc-linux" + libs_softmmu="$libs_softmmu -latomic" + else + error_exit "libatomic check failed" + fi +fi + ########################################## # check if we have VSS SDK headers for win diff --git a/exec.c b/exec.c index 8ffde75983..3ac8a823e2 100644 --- a/exec.c +++ b/exec.c @@ -1230,11 +1230,13 @@ static void *file_ram_alloc(RAMBlock *block, int fd = -1; int64_t page_size; +#ifndef TARGET_PPC if (kvm_enabled() && !kvm_has_sync_mmu()) { error_setg(errp, "host lacks kvm mmu notifiers, -mem-path unsupported"); return NULL; } +#endif for (;;) { fd = open(path, O_RDWR); diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index 54f7ad1c48..b4bf2f40c9 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -9,6 +9,13 @@ * the COPYING file in the top-level directory. */ +/* work around a broken sys/capability.h */ +#if defined(__i386__) +typedef unsigned long long __u64; +#endif +#if defined(__powerpc64__) +#include +#endif #include "qemu/osdep.h" #include #include diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c index 3b8ad33fc5..6f37eeb433 100644 --- a/hw/block/xen_disk.c +++ b/hw/block/xen_disk.c @@ -111,6 +111,7 @@ struct XenBlkDev { int requests_inflight; int requests_finished; + gboolean cache_unsafe; /* Persistent grants extension */ gboolean feature_discard; gboolean feature_persistent; @@ -793,6 +794,16 @@ static void blk_parse_discard(struct XenBlkDev *blkdev) } } +static void blk_parse_cache_unsafe(struct XenBlkDev *blkdev) +{ + int enable; + + blkdev->cache_unsafe = false; + + if (xenstore_read_be_int(&blkdev->xendev, "suse-diskcache-disable-flush", &enable) == 0) + blkdev->cache_unsafe = !!enable; +} + static int blk_init(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); @@ -864,6 +875,7 @@ static int blk_init(struct XenDevice *xendev) xenstore_write_be_int(&blkdev->xendev, "info", info); blk_parse_discard(blkdev); + blk_parse_cache_unsafe(blkdev); g_free(directiosafe); return 0; @@ -906,6 +918,9 @@ static int blk_connect(struct XenDevice *xendev) qflags |= BDRV_O_UNMAP; } + if (blkdev->cache_unsafe) + qflags |= BDRV_O_NO_FLUSH; + /* init qemu block driver */ index = (blkdev->xendev.dev - 202 * 256) / 16; blkdev->dinfo = drive_get(IF_XEN, 0, index); diff --git a/hw/i386/xen/xen_platform.c b/hw/i386/xen/xen_platform.c index aa7839324c..48800c122a 100644 --- a/hw/i386/xen/xen_platform.c +++ b/hw/i386/xen/xen_platform.c @@ -314,6 +314,28 @@ static void xen_platform_ioport_writeb(void *opaque, hwaddr addr, case 0: /* Platform flags */ platform_fixed_ioport_writeb(opaque, 0, (uint32_t)val); break; + case 4: + if (val == 1 && size == 1) { + /* + * SUSE unplug for Xenlinux + * xen-kmp used this since xen-3.0.4, instead the official protocol from xen-3.3+ + * It did an unconditional "outl(1, (ioaddr + 4));" + * This approach was used until openSUSE 12.3, up to SLE11SP3 and in SLE10. + * Starting with openSUSE 13.1, SLE11SP4 and SLE12 the official protocol is used. + * pre VMDP 1.7 made use of 4 and 8 depending on how vmdp was configured. + * If VMDP was to control both disk and LAN it would use 4. + * If it controlled just disk or just LAN, it would use 8 below. + */ + PCIDevice *pci_dev = PCI_DEVICE(s); + DPRINTF("unplug disks\n"); + blk_drain_all(); + blk_flush_all(); + pci_unplug_disks(pci_dev->bus); + DPRINTF("unplug nics\n"); + pci_unplug_nics(pci_dev->bus); + DPRINTF("done\n"); + } + break; case 8: log_writeb(s, (uint32_t)val); break; diff --git a/include/exec/user/thunk.h b/include/exec/user/thunk.h index f19ef4b230..b2659e0def 100644 --- a/include/exec/user/thunk.h +++ b/include/exec/user/thunk.h @@ -37,6 +37,7 @@ typedef enum argtype { TYPE_ARRAY, TYPE_STRUCT, TYPE_OLDDEVT, + TYPE_INTBITFIELD, } argtype; #define MK_PTR(type) TYPE_PTR, type @@ -89,6 +90,7 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host) case TYPE_SHORT: return 2; case TYPE_INT: + case TYPE_INTBITFIELD: return 4; case TYPE_LONGLONG: case TYPE_ULONGLONG: @@ -151,6 +153,7 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host) case TYPE_SHORT: return 2; case TYPE_INT: + case TYPE_INTBITFIELD: return 4; case TYPE_LONGLONG: case TYPE_ULONGLONG: diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 8c93058100..607ca2dc92 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -6,3 +6,5 @@ obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o obj-$(TARGET_ARM) += arm/nwfpe/ obj-$(TARGET_M68K) += m68k-sim.o + +obj-binfmt-y = binfmt.o diff --git a/linux-user/binfmt.c b/linux-user/binfmt.c new file mode 100644 index 0000000000..458f136fb4 --- /dev/null +++ b/linux-user/binfmt.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include + +#ifdef __x86_64__ +#define ARCH_NAME "x86_64" +#endif + +int main(int argc, char **argv, char **envp) +{ + char *binfmt; + char **new_argv; + + /* + * Check if our file name ends with -binfmt + */ + binfmt = argv[0] + strlen(argv[0]) - strlen("-binfmt"); + if (strcmp(binfmt, "-binfmt")) { + fprintf(stderr, "%s: Invalid executable name\n", argv[0]); + exit(1); + } + if (argc < 3) { + fprintf(stderr, "%s: Please use me through binfmt with P flag\n", + argv[0]); + exit(1); + } + + binfmt[0] = '\0'; + /* Now argv[0] is the real qemu binary name */ + +#ifdef ARCH_NAME + { + char *hostbin; + char *guestarch; + int r; + + guestarch = strrchr(argv[0], '-') ; + if (!guestarch) { + goto skip; + } + guestarch++; + r = asprintf(&hostbin, "/emul/" ARCH_NAME "-for-%s/%s", guestarch, argv[1]); + if ((r > 0) && !access(hostbin, X_OK)) { + /* + * We found a host binary replacement for the non-host binary. Let's + * use that instead! + */ + return execve(hostbin, &argv[2], envp); + } + } +skip: +#endif + + new_argv = (char **)malloc((argc + 2) * sizeof(*new_argv)); + if (argc > 3) { + memcpy(&new_argv[4], &argv[3], (argc - 3) * sizeof(*new_argv)); + } + new_argv[0] = argv[0]; + new_argv[1] = (char *)"-0"; + new_argv[2] = argv[2]; + new_argv[3] = argv[1]; + new_argv[argc + 1] = NULL; + + return execve(new_argv[0], new_argv, envp); +} diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 7e2c133ba1..8a5be00aeb 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -119,6 +119,8 @@ IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap, MK_PTR(MK_STRUCT(STRUCT_fiemap))) #endif + IOCTL(FS_IOC_GETFLAGS, IOC_R, MK_PTR(TYPE_LONG)) + IOCTL(FS_IOC_SETFLAGS, IOC_W, MK_PTR(TYPE_LONG)) IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) @@ -348,6 +350,11 @@ IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2))) IOCTL(VFAT_IOCTL_READDIR_SHORT, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2))) +/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */ +#ifdef __powerpc__ +#include "ioctls_alsa.h" +#endif + IOCTL(LOOP_SET_FD, 0, TYPE_INT) IOCTL(LOOP_CLR_FD, 0, TYPE_INT) IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) diff --git a/linux-user/ioctls_alsa.h b/linux-user/ioctls_alsa.h new file mode 100644 index 0000000000..c2aa542c3b --- /dev/null +++ b/linux-user/ioctls_alsa.h @@ -0,0 +1,467 @@ +#define SNDRV_SEQ_IOCTL_PVERSION _IOR ('S', 0x00, int) +#define SNDRV_SEQ_IOCTL_CLIENT_ID _IOR ('S', 0x01, int) +#define SNDRV_SEQ_IOCTL_SYSTEM_INFO _IOWR('S', 0x02, struct sndrv_seq_system_info) +#define SNDRV_SEQ_IOCTL_RUNNING_MODE _IOWR('S', 0x03, struct sndrv_seq_running_info) +#define SNDRV_SEQ_IOCTL_GET_CLIENT_INFO _IOWR('S', 0x10, struct sndrv_seq_client_info) +#define SNDRV_SEQ_IOCTL_SET_CLIENT_INFO _IOW ('S', 0x11, struct sndrv_seq_client_info) +#define SNDRV_SEQ_IOCTL_CREATE_PORT _IOWR('S', 0x20, struct sndrv_seq_port_info) +#define SNDRV_SEQ_IOCTL_DELETE_PORT _IOW ('S', 0x21, struct sndrv_seq_port_info) +#define SNDRV_SEQ_IOCTL_GET_PORT_INFO _IOWR('S', 0x22, struct sndrv_seq_port_info) +#define SNDRV_SEQ_IOCTL_SET_PORT_INFO _IOW ('S', 0x23, struct sndrv_seq_port_info) +#define SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT _IOW ('S', 0x30, struct sndrv_seq_port_subscribe) +#define SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT _IOW ('S', 0x31, struct sndrv_seq_port_subscribe) +#define SNDRV_SEQ_IOCTL_CREATE_QUEUE _IOWR('S', 0x32, struct sndrv_seq_queue_info) +#define SNDRV_SEQ_IOCTL_DELETE_QUEUE _IOW ('S', 0x33, struct sndrv_seq_queue_info) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_INFO _IOWR('S', 0x34, struct sndrv_seq_queue_info) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_INFO _IOWR('S', 0x35, struct sndrv_seq_queue_info) +#define SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE _IOWR('S', 0x36, struct sndrv_seq_queue_info) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS _IOWR('S', 0x40, struct sndrv_seq_queue_status) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO _IOWR('S', 0x41, struct sndrv_seq_queue_tempo) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO _IOW ('S', 0x42, struct sndrv_seq_queue_tempo) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER _IOWR('S', 0x43, struct sndrv_seq_queue_owner) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER _IOW ('S', 0x44, struct sndrv_seq_queue_owner) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER _IOWR('S', 0x45, struct sndrv_seq_queue_timer) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER _IOW ('S', 0x46, struct sndrv_seq_queue_timer) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC _IOWR('S', 0x53, struct sndrv_seq_queue_sync) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC _IOW ('S', 0x54, struct sndrv_seq_queue_sync) +#define SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT _IOWR('S', 0x49, struct sndrv_seq_queue_client) +#define SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT _IOW ('S', 0x4a, struct sndrv_seq_queue_client) +#define SNDRV_SEQ_IOCTL_GET_CLIENT_POOL _IOWR('S', 0x4b, struct sndrv_seq_client_pool) +#define SNDRV_SEQ_IOCTL_SET_CLIENT_POOL _IOW ('S', 0x4c, struct sndrv_seq_client_pool) +#define SNDRV_SEQ_IOCTL_REMOVE_EVENTS _IOW ('S', 0x4e, struct sndrv_seq_remove_events) +#define SNDRV_SEQ_IOCTL_QUERY_SUBS _IOWR('S', 0x4f, struct sndrv_seq_query_subs) +#define SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION _IOWR('S', 0x50, struct sndrv_seq_port_subscribe) +#define SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT _IOWR('S', 0x51, struct sndrv_seq_client_info) +#define SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT _IOWR('S', 0x52, struct sndrv_seq_port_info) +#define SNDRV_DM_FM_IOCTL_INFO _IOR('H', 0x20, snd_dm_fm_info_t) +#define SNDRV_DM_FM_IOCTL_RESET _IO ('H', 0x21) +#define SNDRV_DM_FM_IOCTL_PLAY_NOTE _IOW('H', 0x22, snd_dm_fm_note_t) +#define SNDRV_DM_FM_IOCTL_SET_VOICE _IOW('H', 0x23, snd_dm_fm_voice_t) +#define SNDRV_DM_FM_IOCTL_SET_PARAMS _IOW('H', 0x24, snd_dm_fm_params_t) +#define SNDRV_DM_FM_IOCTL_SET_MODE _IOW('H', 0x25, int) +#define SNDRV_DM_FM_IOCTL_SET_CONNECTION _IOW('H', 0x26, int) +#define SNDRV_DM_FM_OSS_IOCTL_RESET 0x20 +#define SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21 +#define SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22 +#define SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23 +#define SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24 +#define SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25 +#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int) +#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct sndrv_hwdep_info) +#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct sndrv_hwdep_dsp_status) +#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct sndrv_hwdep_dsp_image) +#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) +#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct sndrv_pcm_info) +#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) +#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct sndrv_pcm_hw_params) +#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct sndrv_pcm_hw_params) +#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) +#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct sndrv_pcm_sw_params) +#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct sndrv_pcm_status) +#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, sndrv_pcm_sframes_t) +#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22) +#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr) +#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct sndrv_pcm_channel_info) +#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40) +#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41) +#define SNDRV_PCM_IOCTL_START _IO('A', 0x42) +#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43) +#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44) +#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int) +#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, sndrv_pcm_uframes_t) +#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47) +#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48) +#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, sndrv_pcm_uframes_t) +#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct sndrv_xferi) +#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct sndrv_xferi) +#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct sndrv_xfern) +#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct sndrv_xfern) +#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int) +#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61) +#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int) +#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct sndrv_rawmidi_info) +#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct sndrv_rawmidi_params) +#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct sndrv_rawmidi_status) +#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int) +#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int) +#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int) +#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct sndrv_timer_id) +#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int) +#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct sndrv_timer_ginfo) +#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct sndrv_timer_gparams) +#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct sndrv_timer_gstatus) +#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct sndrv_timer_select) +#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct sndrv_timer_info) +#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct sndrv_timer_params) +#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct sndrv_timer_status) +#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0) +#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1) +#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2) +#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3) +#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int) +#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct sndrv_ctl_card_info) +#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct sndrv_ctl_elem_list) +#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct sndrv_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct sndrv_ctl_elem_value) +#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct sndrv_ctl_elem_value) +#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct sndrv_ctl_elem_id) +#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct sndrv_ctl_elem_id) +#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int) +#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct sndrv_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct sndrv_ctl_elem_info) +#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct sndrv_ctl_elem_id) +#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct sndrv_ctl_tlv) +#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct sndrv_ctl_tlv) +#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct sndrv_ctl_tlv) +#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int) +#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct sndrv_hwdep_info) +#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int) +#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct sndrv_pcm_info) +#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int) +#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int) +#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct sndrv_rawmidi_info) +#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int) +#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int) +#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int) +#define SNDRV_IOCTL_READV _IOW('K', 0x00, struct sndrv_xferv) +#define SNDRV_IOCTL_WRITEV _IOW('K', 0x01, struct sndrv_xferv) +#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, emu10k1_fx8010_info_t) +#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, emu10k1_fx8010_code_t) +#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, emu10k1_fx8010_code_t) +#define SNDRV_EMU10K1_IOCTL_TRAM_SETUP _IOW ('H', 0x20, int) +#define SNDRV_EMU10K1_IOCTL_TRAM_POKE _IOW ('H', 0x21, emu10k1_fx8010_tram_t) +#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, emu10k1_fx8010_tram_t) +#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, emu10k1_fx8010_pcm_t) +#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, emu10k1_fx8010_pcm_t) +#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int) +#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) +#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) +#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) +#define SNDRV_EMU10K1_IOCTL_SINGLE_STEP _IOW ('H', 0x83, int) +#define SNDRV_EMU10K1_IOCTL_DBG_READ _IOR ('H', 0x84, int) +#define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, hdsp_peak_rms_t) +#define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdsp_config_info_t) +#define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, hdsp_firmware_t) +#define SNDRV_HDSP_IOCTL_GET_VERSION _IOR('H', 0x43, hdsp_version_t) +#define SNDRV_HDSP_IOCTL_GET_MIXER _IOR('H', 0x44, hdsp_mixer_t) +#define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, hdsp_9632_aeb_t) +#define SNDRV_SB_CSP_IOCTL_INFO _IOR('H', 0x10, snd_sb_csp_info_t) +#define SNDRV_SB_CSP_IOCTL_LOAD_CODE _IOW('H', 0x11, snd_sb_csp_microcode_t) +#define SNDRV_SB_CSP_IOCTL_UNLOAD_CODE _IO('H', 0x12) +#define SNDRV_SB_CSP_IOCTL_START _IOW('H', 0x13, snd_sb_csp_start_t) +#define SNDRV_SB_CSP_IOCTL_STOP _IO('H', 0x14) +#define SNDRV_SB_CSP_IOCTL_PAUSE _IO('H', 0x15) +#define SNDRV_SB_CSP_IOCTL_RESTART _IO('H', 0x16) +#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock) +#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode) + + +#define TARGET_SNDRV_SEQ_IOCTL_PVERSION TARGET_IOR ('S', 0x00, int) +#define TARGET_SNDRV_SEQ_IOCTL_CLIENT_ID TARGET_IOR ('S', 0x01, int) +#define TARGET_SNDRV_SEQ_IOCTL_SYSTEM_INFO TARGET_IOWRU('S', 0x02) +#define TARGET_SNDRV_SEQ_IOCTL_RUNNING_MODE TARGET_IOWRU('S', 0x03) +#define TARGET_SNDRV_SEQ_IOCTL_GET_CLIENT_INFO TARGET_IOWRU('S', 0x10) +#define TARGET_SNDRV_SEQ_IOCTL_SET_CLIENT_INFO TARGET_IOWU ('S', 0x11) +#define TARGET_SNDRV_SEQ_IOCTL_CREATE_PORT TARGET_IOWRU('S', 0x20) +#define TARGET_SNDRV_SEQ_IOCTL_DELETE_PORT TARGET_IOWU ('S', 0x21) +#define TARGET_SNDRV_SEQ_IOCTL_GET_PORT_INFO TARGET_IOWRU('S', 0x22) +#define TARGET_SNDRV_SEQ_IOCTL_SET_PORT_INFO TARGET_IOWU ('S', 0x23) +#define TARGET_SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT TARGET_IOWU ('S', 0x30) +#define TARGET_SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT TARGET_IOWU ('S', 0x31) +#define TARGET_SNDRV_SEQ_IOCTL_CREATE_QUEUE TARGET_IOWRU('S', 0x32) +#define TARGET_SNDRV_SEQ_IOCTL_DELETE_QUEUE TARGET_IOWU ('S', 0x33) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_INFO TARGET_IOWRU('S', 0x34) +#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_INFO TARGET_IOWRU('S', 0x35) +#define TARGET_SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE TARGET_IOWRU('S', 0x36) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS TARGET_IOWRU('S', 0x40) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO TARGET_IOWRU('S', 0x41) +#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO TARGET_IOWU ('S', 0x42) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER TARGET_IOWRU('S', 0x43) +#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER TARGET_IOWU ('S', 0x44) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER TARGET_IOWRU('S', 0x45) +#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER TARGET_IOWU ('S', 0x46) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC TARGET_IOWRU('S', 0x53) +#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC TARGET_IOWU ('S', 0x54) +#define TARGET_SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT TARGET_IOWRU('S', 0x49) +#define TARGET_SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT TARGET_IOWU ('S', 0x4a) +#define TARGET_SNDRV_SEQ_IOCTL_GET_CLIENT_POOL TARGET_IOWRU('S', 0x4b) +#define TARGET_SNDRV_SEQ_IOCTL_SET_CLIENT_POOL TARGET_IOWU ('S', 0x4c) +#define TARGET_SNDRV_SEQ_IOCTL_REMOVE_EVENTS TARGET_IOWU ('S', 0x4e) +#define TARGET_SNDRV_SEQ_IOCTL_QUERY_SUBS TARGET_IOWRU('S', 0x4f) +#define TARGET_SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION TARGET_IOWRU('S', 0x50) +#define TARGET_SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT TARGET_IOWRU('S', 0x51) +#define TARGET_SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT TARGET_IOWRU('S', 0x52) +#define TARGET_SNDRV_DM_FM_IOCTL_INFO TARGET_IORU('H', 0x20) +#define TARGET_SNDRV_DM_FM_IOCTL_RESET TARGET_IO ('H', 0x21) +#define TARGET_SNDRV_DM_FM_IOCTL_PLAY_NOTE TARGET_IOWU('H', 0x22) +#define TARGET_SNDRV_DM_FM_IOCTL_SET_VOICE TARGET_IOWU('H', 0x23) +#define TARGET_SNDRV_DM_FM_IOCTL_SET_PARAMS TARGET_IOWU('H', 0x24) +#define TARGET_SNDRV_DM_FM_IOCTL_SET_MODE TARGET_IOW('H', 0x25, int) +#define TARGET_SNDRV_DM_FM_IOCTL_SET_CONNECTION TARGET_IOW('H', 0x26, int) +#define TARGET_SNDRV_DM_FM_OSS_IOCTL_RESET 0x20 +#define TARGET_SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE 0x21 +#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_VOICE 0x22 +#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS 0x23 +#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_MODE 0x24 +#define TARGET_SNDRV_DM_FM_OSS_IOCTL_SET_OPL 0x25 +#define TARGET_SNDRV_HWDEP_IOCTL_PVERSION TARGET_IOR ('H', 0x00, int) +#define TARGET_SNDRV_HWDEP_IOCTL_INFO TARGET_IORU ('H', 0x01) +#define TARGET_SNDRV_HWDEP_IOCTL_DSP_STATUS TARGET_IORU('H', 0x02) +#define TARGET_SNDRV_HWDEP_IOCTL_DSP_LOAD TARGET_IOWU('H', 0x03) +#define TARGET_SNDRV_PCM_IOCTL_PVERSION TARGET_IOR('A', 0x00, int) +#define TARGET_SNDRV_PCM_IOCTL_INFO TARGET_IORU('A', 0x01) +#define TARGET_SNDRV_PCM_IOCTL_TSTAMP TARGET_IOW('A', 0x02, int) +#define TARGET_SNDRV_PCM_IOCTL_HW_REFINE TARGET_IOWRU('A', 0x10) +#define TARGET_SNDRV_PCM_IOCTL_HW_PARAMS TARGET_IOWRU('A', 0x11) +#define TARGET_SNDRV_PCM_IOCTL_HW_FREE TARGET_IO('A', 0x12) +#define TARGET_SNDRV_PCM_IOCTL_SW_PARAMS TARGET_IOWRU('A', 0x13) +#define TARGET_SNDRV_PCM_IOCTL_STATUS TARGET_IORU('A', 0x20) +#define TARGET_SNDRV_PCM_IOCTL_DELAY TARGET_IORU('A', 0x21) +#define TARGET_SNDRV_PCM_IOCTL_HWSYNC TARGET_IO('A', 0x22) +#define TARGET_SNDRV_PCM_IOCTL_SYNC_PTR TARGET_IOWRU('A', 0x23) +#define TARGET_SNDRV_PCM_IOCTL_CHANNEL_INFO TARGET_IORU('A', 0x32) +#define TARGET_SNDRV_PCM_IOCTL_PREPARE TARGET_IO('A', 0x40) +#define TARGET_SNDRV_PCM_IOCTL_RESET TARGET_IO('A', 0x41) +#define TARGET_SNDRV_PCM_IOCTL_START TARGET_IO('A', 0x42) +#define TARGET_SNDRV_PCM_IOCTL_DROP TARGET_IO('A', 0x43) +#define TARGET_SNDRV_PCM_IOCTL_DRAIN TARGET_IO('A', 0x44) +#define TARGET_SNDRV_PCM_IOCTL_PAUSE TARGET_IOW('A', 0x45, int) +#define TARGET_SNDRV_PCM_IOCTL_REWIND TARGET_IOWU('A', 0x46) +#define TARGET_SNDRV_PCM_IOCTL_RESUME TARGET_IO('A', 0x47) +#define TARGET_SNDRV_PCM_IOCTL_XRUN TARGET_IO('A', 0x48) +#define TARGET_SNDRV_PCM_IOCTL_FORWARD TARGET_IOWU('A', 0x49) +#define TARGET_SNDRV_PCM_IOCTL_WRITEI_FRAMES TARGET_IOWU('A', 0x50) +#define TARGET_SNDRV_PCM_IOCTL_READI_FRAMES TARGET_IORU('A', 0x51) +#define TARGET_SNDRV_PCM_IOCTL_WRITEN_FRAMES TARGET_IOWU('A', 0x52) +#define TARGET_SNDRV_PCM_IOCTL_READN_FRAMES TARGET_IORU('A', 0x53) +#define TARGET_SNDRV_PCM_IOCTL_LINK TARGET_IOW('A', 0x60, int) +#define TARGET_SNDRV_PCM_IOCTL_UNLINK TARGET_IO('A', 0x61) +#define TARGET_SNDRV_RAWMIDI_IOCTL_PVERSION TARGET_IOR('W', 0x00, int) +#define TARGET_SNDRV_RAWMIDI_IOCTL_INFO TARGET_IORU('W', 0x01) +#define TARGET_SNDRV_RAWMIDI_IOCTL_PARAMS TARGET_IOWRU('W', 0x10) +#define TARGET_SNDRV_RAWMIDI_IOCTL_STATUS TARGET_IOWRU('W', 0x20) +#define TARGET_SNDRV_RAWMIDI_IOCTL_DROP TARGET_IOW('W', 0x30, int) +#define TARGET_SNDRV_RAWMIDI_IOCTL_DRAIN TARGET_IOW('W', 0x31, int) +#define TARGET_SNDRV_TIMER_IOCTL_PVERSION TARGET_IOR('T', 0x00, int) +#define TARGET_SNDRV_TIMER_IOCTL_NEXT_DEVICE TARGET_IOWRU('T', 0x01) +#define TARGET_SNDRV_TIMER_IOCTL_TREAD TARGET_IOW('T', 0x02, int) +#define TARGET_SNDRV_TIMER_IOCTL_GINFO TARGET_IOWRU('T', 0x03) +#define TARGET_SNDRV_TIMER_IOCTL_GPARAMS TARGET_IOWU('T', 0x04) +#define TARGET_SNDRV_TIMER_IOCTL_GSTATUS TARGET_IOWRU('T', 0x05) +#define TARGET_SNDRV_TIMER_IOCTL_SELECT TARGET_IOWU('T', 0x10) +#define TARGET_SNDRV_TIMER_IOCTL_INFO TARGET_IORU('T', 0x11) +#define TARGET_SNDRV_TIMER_IOCTL_PARAMS TARGET_IOWU('T', 0x12) +#define TARGET_SNDRV_TIMER_IOCTL_STATUS TARGET_IORU('T', 0x14) +#define TARGET_SNDRV_TIMER_IOCTL_START TARGET_IO('T', 0xa0) +#define TARGET_SNDRV_TIMER_IOCTL_STOP TARGET_IO('T', 0xa1) +#define TARGET_SNDRV_TIMER_IOCTL_CONTINUE TARGET_IO('T', 0xa2) +#define TARGET_SNDRV_TIMER_IOCTL_PAUSE TARGET_IO('T', 0xa3) +#define TARGET_SNDRV_CTL_IOCTL_PVERSION TARGET_IOR('U', 0x00, int) +#define TARGET_SNDRV_CTL_IOCTL_CARD_INFO TARGET_IORU('U', 0x01) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_LIST TARGET_IOWRU('U', 0x10) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_INFO TARGET_IOWRU('U', 0x11) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_READ TARGET_IOWRU('U', 0x12) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_WRITE TARGET_IOWRU('U', 0x13) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_LOCK TARGET_IOWU('U', 0x14) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_UNLOCK TARGET_IOWU('U', 0x15) +#define TARGET_SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS TARGET_IOWR('U', 0x16, int) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_ADD TARGET_IOWRU('U', 0x17) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_REPLACE TARGET_IOWRU('U', 0x18) +#define TARGET_SNDRV_CTL_IOCTL_ELEM_REMOVE TARGET_IOWRU('U', 0x19) +#define TARGET_SNDRV_CTL_IOCTL_TLV_READ TARGET_IOWRU('U', 0x1a) +#define TARGET_SNDRV_CTL_IOCTL_TLV_WRITE TARGET_IOWRU('U', 0x1b) +#define TARGET_SNDRV_CTL_IOCTL_TLV_COMMAND TARGET_IOWRU('U', 0x1c) +#define TARGET_SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE TARGET_IOWR('U', 0x20, int) +#define TARGET_SNDRV_CTL_IOCTL_HWDEP_INFO TARGET_IORU('U', 0x21) +#define TARGET_SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE TARGET_IOR('U', 0x30, int) +#define TARGET_SNDRV_CTL_IOCTL_PCM_INFO TARGET_IOWRU('U', 0x31) +#define TARGET_SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE TARGET_IOW('U', 0x32, int) +#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE TARGET_IOWR('U', 0x40, int) +#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_INFO TARGET_IOWRU('U', 0x41) +#define TARGET_SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE TARGET_IOW('U', 0x42, int) +#define TARGET_SNDRV_CTL_IOCTL_POWER TARGET_IOWR('U', 0xd0, int) +#define TARGET_SNDRV_CTL_IOCTL_POWER_STATE TARGET_IOR('U', 0xd1, int) +#define TARGET_SNDRV_IOCTL_READV TARGET_IOWU('K', 0x00) +#define TARGET_SNDRV_IOCTL_WRITEV TARGET_IOWU('K', 0x01) +#define TARGET_SNDRV_EMU10K1_IOCTL_INFO TARGET_IORU ('H', 0x10) +#define TARGET_SNDRV_EMU10K1_IOCTL_CODE_POKE TARGET_IOWU ('H', 0x11) +#define TARGET_SNDRV_EMU10K1_IOCTL_CODE_PEEK TARGET_IOWRU('H', 0x12) +#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_SETUP TARGET_IOW ('H', 0x20, int) +#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_POKE TARGET_IOWU ('H', 0x21) +#define TARGET_SNDRV_EMU10K1_IOCTL_TRAM_PEEK TARGET_IOWRU('H', 0x22) +#define TARGET_SNDRV_EMU10K1_IOCTL_PCM_POKE TARGET_IOWU ('H', 0x30) +#define TARGET_SNDRV_EMU10K1_IOCTL_PCM_PEEK TARGET_IOWRU('H', 0x31) +#define TARGET_SNDRV_EMU10K1_IOCTL_PVERSION TARGET_IOR ('H', 0x40, int) +#define TARGET_SNDRV_EMU10K1_IOCTL_STOP TARGET_IO ('H', 0x80) +#define TARGET_SNDRV_EMU10K1_IOCTL_CONTINUE TARGET_IO ('H', 0x81) +#define TARGET_SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER TARGET_IO ('H', 0x82) +#define TARGET_SNDRV_EMU10K1_IOCTL_SINGLE_STEP TARGET_IOW ('H', 0x83, int) +#define TARGET_SNDRV_EMU10K1_IOCTL_DBG_READ TARGET_IOR ('H', 0x84, int) +#define TARGET_SNDRV_HDSP_IOCTL_GET_PEAK_RMS TARGET_IORU('H', 0x40) +#define TARGET_SNDRV_HDSP_IOCTL_GET_CONFIG_INFO TARGET_IORU('H', 0x41) +#define TARGET_SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE TARGET_IOWU('H', 0x42) +#define TARGET_SNDRV_HDSP_IOCTL_GET_VERSION TARGET_IORU('H', 0x43) +#define TARGET_SNDRV_HDSP_IOCTL_GET_MIXER TARGET_IORU('H', 0x44) +#define TARGET_SNDRV_HDSP_IOCTL_GET_9632_AEB TARGET_IORU('H', 0x45) +#define TARGET_SNDRV_SB_CSP_IOCTL_INFO TARGET_IORU('H', 0x10) +#define TARGET_SNDRV_SB_CSP_IOCTL_LOAD_CODE TARGET_IOWU('H', 0x11) +#define TARGET_SNDRV_SB_CSP_IOCTL_UNLOAD_CODE TARGET_IO('H', 0x12) +#define TARGET_SNDRV_SB_CSP_IOCTL_START TARGET_IOWU('H', 0x13) +#define TARGET_SNDRV_SB_CSP_IOCTL_STOP TARGET_IO('H', 0x14) +#define TARGET_SNDRV_SB_CSP_IOCTL_PAUSE TARGET_IO('H', 0x15) +#define TARGET_SNDRV_SB_CSP_IOCTL_RESTART TARGET_IO('H', 0x16) +#define TARGET_SND_SSCAPE_LOAD_BOOTB TARGET_IOWRU('P', 100) +#define TARGET_SND_SSCAPE_LOAD_MCODE TARGET_IOWU ('P', 101) + +IOCTL( SNDRV_SEQ_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_SEQ_IOCTL_CLIENT_ID , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_SEQ_IOCTL_SYSTEM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_system_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_RUNNING_MODE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_running_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_CLIENT_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_CLIENT_INFO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_CREATE_PORT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_DELETE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_PORT_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_PORT_INFO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) ) +IOCTL( SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) ) +IOCTL( SNDRV_SEQ_IOCTL_CREATE_QUEUE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_DELETE_QUEUE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_status)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_tempo)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_tempo)) ) +//IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_owner)) ) +//IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_owner)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_timer)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_timer)) ) +//IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_SYNC , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_sync)) ) +//IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_SYNC , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_sync)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_client)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_queue_client)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_CLIENT_POOL , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_pool)) ) +IOCTL( SNDRV_SEQ_IOCTL_SET_CLIENT_POOL , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_pool)) ) +IOCTL( SNDRV_SEQ_IOCTL_REMOVE_EVENTS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_remove_events)) ) +IOCTL( SNDRV_SEQ_IOCTL_QUERY_SUBS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_query_subs)) ) +IOCTL( SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_subscribe)) ) +IOCTL( SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_client_info)) ) +IOCTL( SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_seq_port_info)) ) +IOCTL( SNDRV_DM_FM_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_info)) ) +IOCTL( SNDRV_DM_FM_IOCTL_RESET , 0, TYPE_NULL ) +IOCTL( SNDRV_DM_FM_IOCTL_PLAY_NOTE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_note)) ) +IOCTL( SNDRV_DM_FM_IOCTL_SET_VOICE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_voice)) ) +IOCTL( SNDRV_DM_FM_IOCTL_SET_PARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_dm_fm_params)) ) +IOCTL( SNDRV_DM_FM_IOCTL_SET_MODE , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_DM_FM_IOCTL_SET_CONNECTION , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_HWDEP_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_HWDEP_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_info)) ) +IOCTL( SNDRV_HWDEP_IOCTL_DSP_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_dsp_status)) ) +IOCTL( SNDRV_HWDEP_IOCTL_DSP_LOAD , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_dsp_image)) ) +IOCTL( SNDRV_PCM_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_PCM_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_info)) ) +IOCTL( SNDRV_PCM_IOCTL_TSTAMP , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_PCM_IOCTL_HW_REFINE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_hw_params)) ) +IOCTL( SNDRV_PCM_IOCTL_HW_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_hw_params)) ) +IOCTL( SNDRV_PCM_IOCTL_HW_FREE , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_SW_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sw_params)) ) +IOCTL( SNDRV_PCM_IOCTL_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_status)) ) +IOCTL( SNDRV_PCM_IOCTL_DELAY , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sframes)) ) +IOCTL( SNDRV_PCM_IOCTL_HWSYNC , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_SYNC_PTR , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_sync_ptr)) ) +IOCTL( SNDRV_PCM_IOCTL_CHANNEL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_channel_info)) ) +IOCTL( SNDRV_PCM_IOCTL_PREPARE , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_RESET , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_START , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_DROP , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_DRAIN , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_PAUSE , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_PCM_IOCTL_REWIND , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_uframes)) ) +IOCTL( SNDRV_PCM_IOCTL_RESUME , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_XRUN , 0, TYPE_NULL ) +IOCTL( SNDRV_PCM_IOCTL_FORWARD , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_uframes)) ) +IOCTL( SNDRV_PCM_IOCTL_WRITEI_FRAMES , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferi)) ) +IOCTL( SNDRV_PCM_IOCTL_READI_FRAMES , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferi)) ) +IOCTL( SNDRV_PCM_IOCTL_WRITEN_FRAMES , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xfern)) ) +IOCTL( SNDRV_PCM_IOCTL_READN_FRAMES , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_xfern)) ) +IOCTL( SNDRV_PCM_IOCTL_LINK , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_PCM_IOCTL_UNLINK , 0, TYPE_NULL ) +IOCTL( SNDRV_RAWMIDI_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_RAWMIDI_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_info)) ) +IOCTL( SNDRV_RAWMIDI_IOCTL_PARAMS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_params)) ) +IOCTL( SNDRV_RAWMIDI_IOCTL_STATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_status)) ) +IOCTL( SNDRV_RAWMIDI_IOCTL_DROP , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_RAWMIDI_IOCTL_DRAIN , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_TIMER_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_TIMER_IOCTL_NEXT_DEVICE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_id)) ) +IOCTL( SNDRV_TIMER_IOCTL_TREAD , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_TIMER_IOCTL_GINFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_ginfo)) ) +IOCTL( SNDRV_TIMER_IOCTL_GPARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_gparams)) ) +IOCTL( SNDRV_TIMER_IOCTL_GSTATUS , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_gstatus)) ) +IOCTL( SNDRV_TIMER_IOCTL_SELECT , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_select)) ) +IOCTL( SNDRV_TIMER_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_info)) ) +IOCTL( SNDRV_TIMER_IOCTL_PARAMS , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_params)) ) +IOCTL( SNDRV_TIMER_IOCTL_STATUS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_timer_status)) ) +IOCTL( SNDRV_TIMER_IOCTL_START , 0, TYPE_NULL ) +IOCTL( SNDRV_TIMER_IOCTL_STOP , 0, TYPE_NULL ) +IOCTL( SNDRV_TIMER_IOCTL_CONTINUE , 0, TYPE_NULL ) +IOCTL( SNDRV_TIMER_IOCTL_PAUSE , 0, TYPE_NULL ) +IOCTL( SNDRV_CTL_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_CARD_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_card_info)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_LIST , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_list)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_READ , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_value)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_WRITE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_value)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_LOCK , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_UNLOCK , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) ) +IOCTL( SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS , IOC_RW, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_ADD , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_REPLACE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_info)) ) +IOCTL( SNDRV_CTL_IOCTL_ELEM_REMOVE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_elem_id)) ) +IOCTL( SNDRV_CTL_IOCTL_TLV_READ , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) ) +IOCTL( SNDRV_CTL_IOCTL_TLV_WRITE , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) ) +IOCTL( SNDRV_CTL_IOCTL_TLV_COMMAND , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_ctl_tlv)) ) +IOCTL( SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE , IOC_RW, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_HWDEP_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_sndrv_hwdep_info)) ) +IOCTL( SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_PCM_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_pcm_info)) ) +IOCTL( SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE , IOC_RW, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_INFO , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sndrv_rawmidi_info)) ) +IOCTL( SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_POWER , IOC_RW, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_CTL_IOCTL_POWER_STATE , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_IOCTL_READV , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferv)) ) +IOCTL( SNDRV_IOCTL_WRITEV , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sndrv_xferv)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_info)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_CODE_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_code)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_CODE_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_code)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_SETUP , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_tram)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_TRAM_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_tram)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_PCM_POKE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_pcm)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_PCM_PEEK , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_emu10k1_fx8010_pcm)) ) +IOCTL( SNDRV_EMU10K1_IOCTL_PVERSION , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_EMU10K1_IOCTL_STOP , 0, TYPE_NULL ) +IOCTL( SNDRV_EMU10K1_IOCTL_CONTINUE , 0, TYPE_NULL ) +IOCTL( SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER , 0, TYPE_NULL ) +IOCTL( SNDRV_EMU10K1_IOCTL_SINGLE_STEP , IOC_W, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_EMU10K1_IOCTL_DBG_READ , IOC_R, MK_PTR(TYPE_INT) ) +IOCTL( SNDRV_HDSP_IOCTL_GET_PEAK_RMS , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_peak_rms)) ) +IOCTL( SNDRV_HDSP_IOCTL_GET_CONFIG_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_config_info)) ) +IOCTL( SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_hdsp_firmware)) ) +IOCTL( SNDRV_HDSP_IOCTL_GET_VERSION , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_version)) ) +IOCTL( SNDRV_HDSP_IOCTL_GET_MIXER , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_mixer)) ) +IOCTL( SNDRV_HDSP_IOCTL_GET_9632_AEB , IOC_R, MK_PTR(MK_STRUCT(STRUCT_hdsp_9632_aeb)) ) +IOCTL( SNDRV_SB_CSP_IOCTL_INFO , IOC_R, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_info)) ) +#if _IOC_SIZEBITS > 13 +IOCTL( SNDRV_SB_CSP_IOCTL_LOAD_CODE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_microcode)) ) +#endif +IOCTL( SNDRV_SB_CSP_IOCTL_UNLOAD_CODE , 0, TYPE_NULL ) +IOCTL( SNDRV_SB_CSP_IOCTL_START , IOC_W, MK_PTR(MK_STRUCT(STRUCT_snd_sb_csp_start)) ) +IOCTL( SNDRV_SB_CSP_IOCTL_STOP , 0, TYPE_NULL ) +IOCTL( SNDRV_SB_CSP_IOCTL_PAUSE , 0, TYPE_NULL ) +IOCTL( SNDRV_SB_CSP_IOCTL_RESTART , 0, TYPE_NULL ) +IOCTL( SND_SSCAPE_LOAD_BOOTB , IOC_RW, MK_PTR(MK_STRUCT(STRUCT_sscape_bootblock)) ) +IOCTL( SND_SSCAPE_LOAD_MCODE , IOC_W, MK_PTR(MK_STRUCT(STRUCT_sscape_microcode)) ) diff --git a/linux-user/ioctls_alsa_structs.h b/linux-user/ioctls_alsa_structs.h new file mode 100644 index 0000000000..e09a30defb --- /dev/null +++ b/linux-user/ioctls_alsa_structs.h @@ -0,0 +1,1740 @@ +/* + * Advanced Linux Sound Architecture + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __u8 +#define __u8 uint8_t +#define __u16 uint16_t +#define __u32 uint32_t +#define __s8 int8_t +#define __s16 int16_t +#define __s32 int32_t +#endif + +#define SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE 0x3000 +#define HDSP_MATRIX_MIXER_SIZE 2048 +#define SNDRV_MASK_MAX 256 + +typedef struct fm_operator { + unsigned char am_vib; + unsigned char ksl_level; + unsigned char attack_decay; + unsigned char sustain_release; + unsigned char wave_select; +} fm_operator_t; + +typedef struct { + unsigned int share_id[4]; /* share id - zero = no sharing */ + unsigned char type; /* instrument type */ + + fm_operator_t op[4]; + unsigned char feedback_connection[2]; + + unsigned char echo_delay; + unsigned char echo_atten; + unsigned char chorus_spread; + unsigned char trnsps; + unsigned char fix_dur; + unsigned char modes; + unsigned char fix_key; +} fm_instrument_t; + +typedef struct fm_xoperator { + __u8 am_vib; + __u8 ksl_level; + __u8 attack_decay; + __u8 sustain_release; + __u8 wave_select; +} fm_xoperator_t; + +typedef struct fm_xinstrument { + __u32 stype; /* structure type */ + + __u32 share_id[4]; /* share id - zero = no sharing */ + __u8 type; /* instrument type */ + + fm_xoperator_t op[4]; /* fm operators */ + __u8 feedback_connection[2]; + + __u8 echo_delay; + __u8 echo_atten; + __u8 chorus_spread; + __u8 trnsps; + __u8 fix_dur; + __u8 modes; + __u8 fix_key; +} fm_xinstrument_t; + +typedef struct gf1_wave { + unsigned int share_id[4]; /* share id - zero = no sharing */ + unsigned int format; /* wave format */ + + struct { + unsigned int number; /* some other ID for this instrument */ + unsigned int memory; /* begin of waveform in onboard memory */ + unsigned char *ptr; /* pointer to waveform in system memory */ + } address; + + unsigned int size; /* size of waveform in samples */ + unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned short loop_repeat; /* loop repeat - 0 = forever */ + + unsigned char flags; /* GF1 patch flags */ + unsigned char pad; + unsigned int sample_rate; /* sample rate in Hz */ + unsigned int low_frequency; /* low frequency range */ + unsigned int high_frequency; /* high frequency range */ + unsigned int root_frequency; /* root frequency range */ + signed short tune; + unsigned char balance; + unsigned char envelope_rate[6]; + unsigned char envelope_offset[6]; + unsigned char tremolo_sweep; + unsigned char tremolo_rate; + unsigned char tremolo_depth; + unsigned char vibrato_sweep; + unsigned char vibrato_rate; + unsigned char vibrato_depth; + unsigned short scale_frequency; + unsigned short scale_factor; /* 0-2048 or 0-2 */ + + struct gf1_wave *next; +} gf1_wave_t; + +typedef struct { + unsigned short exclusion; + unsigned short exclusion_group; /* 0 - none, 1-65535 */ + + unsigned char effect1; /* effect 1 */ + unsigned char effect1_depth; /* 0-127 */ + unsigned char effect2; /* effect 2 */ + unsigned char effect2_depth; /* 0-127 */ + + gf1_wave_t *wave; /* first waveform */ +} gf1_instrument_t; + +typedef struct gf1_xwave { + __u32 stype; /* structure type */ + + __u32 share_id[4]; /* share id - zero = no sharing */ + __u32 format; /* wave format */ + + __u32 size; /* size of waveform in samples */ + __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ + __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + __u16 loop_repeat; /* loop repeat - 0 = forever */ + + __u8 flags; /* GF1 patch flags */ + __u8 pad; + __u32 sample_rate; /* sample rate in Hz */ + __u32 low_frequency; /* low frequency range */ + __u32 high_frequency; /* high frequency range */ + __u32 root_frequency; /* root frequency range */ + __s16 tune; + __u8 balance; + __u8 envelope_rate[6]; + __u8 envelope_offset[6]; + __u8 tremolo_sweep; + __u8 tremolo_rate; + __u8 tremolo_depth; + __u8 vibrato_sweep; + __u8 vibrato_rate; + __u8 vibrato_depth; + __u16 scale_frequency; + __u16 scale_factor; /* 0-2048 or 0-2 */ +} gf1_xwave_t; + +typedef struct gf1_xinstrument { + __u32 stype; + + __u16 exclusion; + __u16 exclusion_group; /* 0 - none, 1-65535 */ + + __u8 effect1; /* effect 1 */ + __u8 effect1_depth; /* 0-127 */ + __u8 effect2; /* effect 2 */ + __u8 effect2_depth; /* 0-127 */ +} gf1_xinstrument_t; + +typedef struct gf1_info { + unsigned char flags; /* supported wave flags */ + unsigned char pad[3]; + unsigned int features; /* supported features */ + unsigned int max8_len; /* maximum 8-bit wave length */ + unsigned int max16_len; /* maximum 16-bit wave length */ +} gf1_info_t; + +typedef struct iwffff_wave { + unsigned int share_id[4]; /* share id - zero = no sharing */ + unsigned int format; /* wave format */ + + struct { + unsigned int number; /* some other ID for this wave */ + unsigned int memory; /* begin of waveform in onboard memory */ + unsigned char *ptr; /* pointer to waveform in system memory */ + } address; + + unsigned int size; /* size of waveform in samples */ + unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned int loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned int loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned short loop_repeat; /* loop repeat - 0 = forever */ + unsigned int sample_ratio; /* sample ratio (44100 * 1024 / rate) */ + unsigned char attenuation; /* 0 - 127 (no corresponding midi controller) */ + unsigned char low_note; /* lower frequency range for this waveform */ + unsigned char high_note; /* higher frequency range for this waveform */ + unsigned char pad; + + struct iwffff_wave *next; +} iwffff_wave_t; + +typedef struct iwffff_lfo { + unsigned short freq; /* (0-2047) 0.01Hz - 21.5Hz */ + signed short depth; /* volume +- (0-255) 0.48675dB/step */ + signed short sweep; /* 0 - 950 deciseconds */ + unsigned char shape; /* see to IWFFFF_LFO_SHAPE_XXXX */ + unsigned char delay; /* 0 - 255 deciseconds */ +} iwffff_lfo_t; + +typedef struct iwffff_env_point { + unsigned short offset; + unsigned short rate; +} iwffff_env_point_t; + +typedef struct iwffff_env_record { + unsigned short nattack; + unsigned short nrelease; + unsigned short sustain_offset; + unsigned short sustain_rate; + unsigned short release_rate; + unsigned char hirange; + unsigned char pad; + struct iwffff_env_record *next; + /* points are stored here */ + /* count of points = nattack + nrelease */ +} iwffff_env_record_t; + +typedef struct iwffff_env { + unsigned char flags; + unsigned char mode; + unsigned char index; + unsigned char pad; + struct iwffff_env_record *record; +} iwffff_env_t; + +typedef struct iwffff_layer { + unsigned char flags; + unsigned char velocity_mode; + unsigned char layer_event; + unsigned char low_range; /* range for layer based */ + unsigned char high_range; /* on either velocity or frequency */ + unsigned char pan; /* pan offset from CC1 (0 left - 127 right) */ + unsigned char pan_freq_scale; /* position based on frequency (0-127) */ + unsigned char attenuation; /* 0-127 (no corresponding midi controller) */ + iwffff_lfo_t tremolo; /* tremolo effect */ + iwffff_lfo_t vibrato; /* vibrato effect */ + unsigned short freq_scale; /* 0-2048, 1024 is equal to semitone scaling */ + unsigned char freq_center; /* center for keyboard frequency scaling */ + unsigned char pad; + iwffff_env_t penv; /* pitch envelope */ + iwffff_env_t venv; /* volume envelope */ + + iwffff_wave_t *wave; + struct iwffff_layer *next; +} iwffff_layer_t; + +typedef struct { + unsigned short exclusion; + unsigned short layer_type; + unsigned short exclusion_group; /* 0 - none, 1-65535 */ + + unsigned char effect1; /* effect 1 */ + unsigned char effect1_depth; /* 0-127 */ + unsigned char effect2; /* effect 2 */ + unsigned char effect2_depth; /* 0-127 */ + + iwffff_layer_t *layer; /* first layer */ +} iwffff_instrument_t; + +typedef struct iwffff_xwave { + __u32 stype; /* structure type */ + + __u32 share_id[4]; /* share id - zero = no sharing */ + + __u32 format; /* wave format */ + __u32 offset; /* offset to ROM (address) */ + + __u32 size; /* size of waveform in samples */ + __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ + __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + __u16 loop_repeat; /* loop repeat - 0 = forever */ + __u32 sample_ratio; /* sample ratio (44100 * 1024 / rate) */ + __u8 attenuation; /* 0 - 127 (no corresponding midi controller) */ + __u8 low_note; /* lower frequency range for this waveform */ + __u8 high_note; /* higher frequency range for this waveform */ + __u8 pad; +} iwffff_xwave_t; + +typedef struct iwffff_xlfo { + __u16 freq; /* (0-2047) 0.01Hz - 21.5Hz */ + __s16 depth; /* volume +- (0-255) 0.48675dB/step */ + __s16 sweep; /* 0 - 950 deciseconds */ + __u8 shape; /* see to ULTRA_IW_LFO_SHAPE_XXXX */ + __u8 delay; /* 0 - 255 deciseconds */ +} iwffff_xlfo_t; + +typedef struct iwffff_xenv_point { + __u16 offset; + __u16 rate; +} iwffff_xenv_point_t; + +typedef struct iwffff_xenv_record { + __u32 stype; + __u16 nattack; + __u16 nrelease; + __u16 sustain_offset; + __u16 sustain_rate; + __u16 release_rate; + __u8 hirange; + __u8 pad; + /* points are stored here.. */ + /* count of points = nattack + nrelease */ +} iwffff_xenv_record_t; + +typedef struct iwffff_xenv { + __u8 flags; + __u8 mode; + __u8 index; + __u8 pad; +} iwffff_xenv_t; + +typedef struct iwffff_xlayer { + __u32 stype; + __u8 flags; + __u8 velocity_mode; + __u8 layer_event; + __u8 low_range; /* range for layer based */ + __u8 high_range; /* on either velocity or frequency */ + __u8 pan; /* pan offset from CC1 (0 left - 127 right) */ + __u8 pan_freq_scale; /* position based on frequency (0-127) */ + __u8 attenuation; /* 0-127 (no corresponding midi controller) */ + iwffff_xlfo_t tremolo; /* tremolo effect */ + iwffff_xlfo_t vibrato; /* vibrato effect */ + __u16 freq_scale; /* 0-2048, 1024 is equal to semitone scaling */ + __u8 freq_center; /* center for keyboard frequency scaling */ + __u8 pad; + iwffff_xenv_t penv; /* pitch envelope */ + iwffff_xenv_t venv; /* volume envelope */ +} iwffff_xlayer_t; + +typedef struct iwffff_xinstrument { + __u32 stype; + + __u16 exclusion; + __u16 layer_type; + __u16 exclusion_group; /* 0 - none, 1-65535 */ + + __u8 effect1; /* effect 1 */ + __u8 effect1_depth; /* 0-127 */ + __u8 effect2; /* effect 2 */ + __u8 effect2_depth; /* 0-127 */ +} iwffff_xinstrument_t; + +typedef struct { + __u8 iwave[8]; + __u8 revision; + __u8 series_number; + __u8 series_name[16]; + __u8 date[10]; + __u16 vendor_revision_major; + __u16 vendor_revision_minor; + __u32 rom_size; + __u8 copyright[128]; + __u8 vendor_name[64]; + __u8 description[128]; +} iwffff_rom_header_t; + +typedef struct iwffff_info { + unsigned int format; /* supported format bits */ + unsigned int effects; /* supported effects (1 << IWFFFF_EFFECT*) */ + unsigned int lfos; /* LFO effects */ + unsigned int max8_len; /* maximum 8-bit wave length */ + unsigned int max16_len; /* maximum 16-bit wave length */ +} iwffff_info_t; + +typedef struct simple_instrument_info { + unsigned int format; /* supported format bits */ + unsigned int effects; /* supported effects (1 << SIMPLE_EFFECT_*) */ + unsigned int max8_len; /* maximum 8-bit wave length */ + unsigned int max16_len; /* maximum 16-bit wave length */ +} simple_instrument_info_t; + +typedef struct { + unsigned int share_id[4]; /* share id - zero = no sharing */ + unsigned int format; /* wave format */ + + struct { + unsigned int number; /* some other ID for this instrument */ + unsigned int memory; /* begin of waveform in onboard memory */ + unsigned char *ptr; /* pointer to waveform in system memory */ + } address; + + unsigned int size; /* size of waveform in samples */ + unsigned int start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned int loop_start; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned int loop_end; /* loop end offset in samples * 16 (lowest 4 bits - fraction) */ + unsigned short loop_repeat; /* loop repeat - 0 = forever */ + + unsigned char effect1; /* effect 1 */ + unsigned char effect1_depth; /* 0-127 */ + unsigned char effect2; /* effect 2 */ + unsigned char effect2_depth; /* 0-127 */ +} simple_instrument_t; + +typedef struct simple_xinstrument { + __u32 stype; + + __u32 share_id[4]; /* share id - zero = no sharing */ + __u32 format; /* wave format */ + + __u32 size; /* size of waveform in samples */ + __u32 start; /* start offset in samples * 16 (lowest 4 bits - fraction) */ + __u32 loop_start; /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + __u32 loop_end; /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + __u16 loop_repeat; /* loop repeat - 0 = forever */ + + __u8 effect1; /* effect 1 */ + __u8 effect1_depth; /* 0-127 */ + __u8 effect2; /* effect 2 */ + __u8 effect2_depth; /* 0-127 */ +} simple_xinstrument_t; + +typedef unsigned char sndrv_seq_event_type_t; + +/** event address */ +struct sndrv_seq_addr { + unsigned char client; /**< Client number: 0..255, 255 = broadcast to all clients */ + unsigned char port; /**< Port within client: 0..255, 255 = broadcast to all ports */ +}; + +/** port connection */ +struct sndrv_seq_connect { + struct sndrv_seq_addr sender; + struct sndrv_seq_addr dest; +}; + +struct sndrv_seq_ev_note { + unsigned char channel; + unsigned char note; + unsigned char velocity; + unsigned char off_velocity; /* only for SNDRV_SEQ_EVENT_NOTE */ + unsigned int duration; /* only for SNDRV_SEQ_EVENT_NOTE */ +}; + + /* controller event */ +struct sndrv_seq_ev_ctrl { + unsigned char channel; + unsigned char unused1, unused2, unused3; /* pad */ + unsigned int param; + signed int value; +}; + + /* generic set of bytes (12x8 bit) */ +struct sndrv_seq_ev_raw8 { + unsigned char d[12]; /* 8 bit value */ +}; + + /* generic set of integers (3x32 bit) */ +struct sndrv_seq_ev_raw32 { + unsigned int d[3]; /* 32 bit value */ +}; + + /* external stored data */ +struct sndrv_seq_ev_ext { + unsigned int len; /* length of data */ + void *ptr; /* pointer to data (note: maybe 64-bit) */ +} __attribute__((packed)); + +/* Instrument cluster type */ +typedef unsigned int sndrv_seq_instr_cluster_t; + +/* Instrument type */ +struct sndrv_seq_instr { + sndrv_seq_instr_cluster_t cluster; + unsigned int std; /* the upper byte means a private instrument (owner - client #) */ + unsigned short bank; + unsigned short prg; +}; + + /* sample number */ +struct sndrv_seq_ev_sample { + unsigned int std; + unsigned short bank; + unsigned short prg; +}; + + /* sample cluster */ +struct sndrv_seq_ev_cluster { + sndrv_seq_instr_cluster_t cluster; +}; + + /* sample position */ +typedef unsigned int sndrv_seq_position_t; /* playback position (in samples) * 16 */ + + /* sample stop mode */ +enum sndrv_seq_stop_mode { + SAMPLE_STOP_IMMEDIATELY = 0, /* terminate playing immediately */ + SAMPLE_STOP_VENVELOPE = 1, /* finish volume envelope */ + SAMPLE_STOP_LOOP = 2 /* terminate loop and finish wave */ +}; + + /* sample frequency */ +typedef int sndrv_seq_frequency_t; /* playback frequency in HZ * 16 */ + + /* sample volume control; if any value is set to -1 == do not change */ +struct sndrv_seq_ev_volume { + signed short volume; /* range: 0-16383 */ + signed short lr; /* left-right balance; range: 0-16383 */ + signed short fr; /* front-rear balance; range: 0-16383 */ + signed short du; /* down-up balance; range: 0-16383 */ +}; + + /* simple loop redefinition */ +struct sndrv_seq_ev_loop { + unsigned int start; /* loop start (in samples) * 16 */ + unsigned int end; /* loop end (in samples) * 16 */ +}; + +struct sndrv_seq_ev_sample_control { + unsigned char channel; + unsigned char unused1, unused2, unused3; /* pad */ + union { + struct sndrv_seq_ev_sample sample; + struct sndrv_seq_ev_cluster cluster; + sndrv_seq_position_t position; + int stop_mode; + sndrv_seq_frequency_t frequency; + struct sndrv_seq_ev_volume volume; + struct sndrv_seq_ev_loop loop; + unsigned char raw8[8]; + } param; +}; + + + +/* INSTR_BEGIN event */ +struct sndrv_seq_ev_instr_begin { + int timeout; /* zero = forever, otherwise timeout in ms */ +}; + +struct sndrv_seq_result { + int event; /* processed event type */ + int result; +}; + + +struct sndrv_seq_real_time { + unsigned int tv_sec; /* seconds */ + unsigned int tv_nsec; /* nanoseconds */ +}; + +typedef unsigned int sndrv_seq_tick_time_t; /* midi ticks */ + +union sndrv_seq_timestamp { + sndrv_seq_tick_time_t tick; + struct sndrv_seq_real_time time; +}; + +struct sndrv_seq_queue_skew { + unsigned int value; + unsigned int base; +}; + + /* queue timer control */ +struct sndrv_seq_ev_queue_control { + unsigned char queue; /* affected queue */ + unsigned char pad[3]; /* reserved */ + union { + signed int value; /* affected value (e.g. tempo) */ + union sndrv_seq_timestamp time; /* time */ + unsigned int position; /* sync position */ + struct sndrv_seq_queue_skew skew; + unsigned int d32[2]; + unsigned char d8[8]; + } param; +}; + + /* quoted event - inside the kernel only */ +struct sndrv_seq_ev_quote { + struct sndrv_seq_addr origin; /* original sender */ + unsigned short value; /* optional data */ + struct sndrv_seq_event *event; /* quoted event */ +} __attribute__((packed)); + + + /* sequencer event */ +struct sndrv_seq_event { + sndrv_seq_event_type_t type; /* event type */ + unsigned char flags; /* event flags */ + char tag; + + unsigned char queue; /* schedule queue */ + union sndrv_seq_timestamp time; /* schedule time */ + + + struct sndrv_seq_addr source; /* source address */ + struct sndrv_seq_addr dest; /* destination address */ + + union { /* event data... */ + struct sndrv_seq_ev_note note; + struct sndrv_seq_ev_ctrl control; + struct sndrv_seq_ev_raw8 raw8; + struct sndrv_seq_ev_raw32 raw32; + struct sndrv_seq_ev_ext ext; + struct sndrv_seq_ev_queue_control queue; + union sndrv_seq_timestamp time; + struct sndrv_seq_addr addr; + struct sndrv_seq_connect connect; + struct sndrv_seq_result result; + struct sndrv_seq_ev_instr_begin instr_begin; + struct sndrv_seq_ev_sample_control sample; + struct sndrv_seq_ev_quote quote; + } data; +}; + + +/* + * bounce event - stored as variable size data + */ +struct sndrv_seq_event_bounce { + int err; + struct sndrv_seq_event event; + /* external data follows here. */ +}; + +struct sndrv_seq_system_info { + int queues; /* maximum queues count */ + int clients; /* maximum clients count */ + int ports; /* maximum ports per client */ + int channels; /* maximum channels per port */ + int cur_clients; /* current clients */ + int cur_queues; /* current queues */ + char reserved[24]; +}; + +struct sndrv_seq_running_info { + unsigned char client; /* client id */ + unsigned char big_endian; /* 1 = big-endian */ + unsigned char cpu_mode; /* 4 = 32bit, 8 = 64bit */ + unsigned char pad; /* reserved */ + unsigned char reserved[12]; +}; + +enum sndrv_seq_client_type { + NO_CLIENT = 0, + USER_CLIENT = 1, + KERNEL_CLIENT = 2 +}; + +struct sndrv_seq_client_info { + int client; /* client number to inquire */ + int type; /* client type */ + char name[64]; /* client name */ + unsigned int filter; /* filter flags */ + unsigned char multicast_filter[8]; /* multicast filter bitmap */ + unsigned char event_filter[32]; /* event filter bitmap */ + int num_ports; /* RO: number of ports */ + int event_lost; /* number of lost events */ + char reserved[64]; /* for future use */ +}; + +struct sndrv_seq_client_pool { + int client; /* client number to inquire */ + int output_pool; /* outgoing (write) pool size */ + int input_pool; /* incoming (read) pool size */ + int output_room; /* minimum free pool size for select/blocking mode */ + int output_free; /* unused size */ + int input_free; /* unused size */ + char reserved[64]; +}; + +struct sndrv_seq_remove_events { + unsigned int remove_mode; /* Flags that determine what gets removed */ + + union sndrv_seq_timestamp time; + + unsigned char queue; /* Queue for REMOVE_DEST */ + struct sndrv_seq_addr dest; /* Address for REMOVE_DEST */ + unsigned char channel; /* Channel for REMOVE_DEST */ + + int type; /* For REMOVE_EVENT_TYPE */ + char tag; /* Tag for REMOVE_TAG */ + + int reserved[10]; /* To allow for future binary compatibility */ + +}; + +struct sndrv_seq_port_info { + struct sndrv_seq_addr addr; /* client/port numbers */ + char name[64]; /* port name */ + + unsigned int capability; /* port capability bits */ + unsigned int type; /* port type bits */ + int midi_channels; /* channels per MIDI port */ + int midi_voices; /* voices per MIDI port */ + int synth_voices; /* voices per SYNTH port */ + + int read_use; /* R/O: subscribers for output (from this port) */ + int write_use; /* R/O: subscribers for input (to this port) */ + + void *kernel; /* reserved for kernel use (must be NULL) */ + unsigned int flags; /* misc. conditioning */ + unsigned char time_queue; /* queue # for timestamping */ + char reserved[59]; /* for future use */ +}; + +struct sndrv_seq_queue_info { + int queue; /* queue id */ + + /* + * security settings, only owner of this queue can start/stop timer + * etc. if the queue is locked for other clients + */ + int owner; /* client id for owner of the queue */ + int locked:1; /* timing queue locked for other queues */ + char name[64]; /* name of this queue */ + unsigned int flags; /* flags */ + char reserved[60]; /* for future use */ + +}; + +struct sndrv_seq_queue_status { + int queue; /* queue id */ + int events; /* read-only - queue size */ + sndrv_seq_tick_time_t tick; /* current tick */ + struct sndrv_seq_real_time time; /* current time */ + int running; /* running state of queue */ + int flags; /* various flags */ + char reserved[64]; /* for the future */ +}; + +struct sndrv_seq_queue_tempo { + int queue; /* sequencer queue */ + unsigned int tempo; /* current tempo, us/tick */ + int ppq; /* time resolution, ticks/quarter */ + unsigned int skew_value; /* queue skew */ + unsigned int skew_base; /* queue skew base */ + char reserved[24]; /* for the future */ +}; + +struct sndrv_timer_id { + int dev_class; + int dev_sclass; + int card; + int device; + int subdevice; +}; + +struct sndrv_seq_queue_timer { + int queue; /* sequencer queue */ + int type; /* source timer type */ + union { + struct { + struct sndrv_timer_id id; /* ALSA's timer ID */ + unsigned int resolution; /* resolution in Hz */ + } alsa; + } u; + char reserved[64]; /* for the future use */ +}; + +struct sndrv_seq_queue_client { + int queue; /* sequencer queue */ + int client; /* sequencer client */ + int used; /* queue is used with this client + (must be set for accepting events) */ + /* per client watermarks */ + char reserved[64]; /* for future use */ +}; + +struct sndrv_seq_port_subscribe { + struct sndrv_seq_addr sender; /* sender address */ + struct sndrv_seq_addr dest; /* destination address */ + unsigned int voices; /* number of voices to be allocated (0 = don't care) */ + unsigned int flags; /* modes */ + unsigned char queue; /* input time-stamp queue (optional) */ + unsigned char pad[3]; /* reserved */ + char reserved[64]; +}; + +struct sndrv_seq_query_subs { + struct sndrv_seq_addr root; /* client/port id to be searched */ + int type; /* READ or WRITE */ + int index; /* 0..N-1 */ + int num_subs; /* R/O: number of subscriptions on this port */ + struct sndrv_seq_addr addr; /* R/O: result */ + unsigned char queue; /* R/O: result */ + unsigned int flags; /* R/O: result */ + char reserved[64]; /* for future use */ +}; + +/* size of ROM/RAM */ +typedef unsigned int sndrv_seq_instr_size_t; + +struct sndrv_seq_instr_info { + int result; /* operation result */ + unsigned int formats[8]; /* bitmap of supported formats */ + int ram_count; /* count of RAM banks */ + sndrv_seq_instr_size_t ram_sizes[16]; /* size of RAM banks */ + int rom_count; /* count of ROM banks */ + sndrv_seq_instr_size_t rom_sizes[8]; /* size of ROM banks */ + char reserved[128]; +}; + +struct sndrv_seq_instr_status { + int result; /* operation result */ + sndrv_seq_instr_size_t free_ram[16]; /* free RAM in banks */ + int instrument_count; /* count of downloaded instruments */ + char reserved[128]; +}; + +struct sndrv_seq_instr_format_info { + char format[16]; /* format identifier - SNDRV_SEQ_INSTR_ID_* */ + unsigned int len; /* max data length (without this structure) */ +}; + +struct sndrv_seq_instr_format_info_result { + int result; /* operation result */ + char format[16]; /* format identifier */ + unsigned int len; /* filled data length (without this structure) */ +}; + +struct sndrv_seq_instr_data { + char name[32]; /* instrument name */ + char reserved[16]; /* for the future use */ + int type; /* instrument type */ + union { + char format[16]; /* format identifier */ + struct sndrv_seq_instr alias; + } data; +}; + +struct sndrv_seq_instr_header { + union { + struct sndrv_seq_instr instr; + sndrv_seq_instr_cluster_t cluster; + } id; /* instrument identifier */ + unsigned int cmd; /* get/put/free command */ + unsigned int flags; /* query flags (only for get) */ + unsigned int len; /* real instrument data length (without header) */ + int result; /* operation result */ + char reserved[16]; /* for the future */ + struct sndrv_seq_instr_data data; /* instrument data (for put/get result) */ +}; + +struct sndrv_seq_instr_cluster_set { + sndrv_seq_instr_cluster_t cluster; /* cluster identifier */ + char name[32]; /* cluster name */ + int priority; /* cluster priority */ + char reserved[64]; /* for the future use */ +}; + +struct sndrv_seq_instr_cluster_get { + sndrv_seq_instr_cluster_t cluster; /* cluster identifier */ + char name[32]; /* cluster name */ + int priority; /* cluster priority */ + char reserved[64]; /* for the future use */ +}; + +typedef struct snd_dm_fm_info { + unsigned char fm_mode; /* OPL mode, see SNDRV_DM_FM_MODE_XXX */ + unsigned char rhythm; /* percussion mode flag */ +} snd_dm_fm_info_t; + +typedef struct snd_dm_fm_voice { + unsigned char op; /* operator cell (0 or 1) */ + unsigned char voice; /* FM voice (0 to 17) */ + + unsigned char am; /* amplitude modulation */ + unsigned char vibrato; /* vibrato effect */ + unsigned char do_sustain; /* sustain phase */ + unsigned char kbd_scale; /* keyboard scaling */ + unsigned char harmonic; /* 4 bits: harmonic and multiplier */ + unsigned char scale_level; /* 2 bits: decrease output freq rises */ + unsigned char volume; /* 6 bits: volume */ + + unsigned char attack; /* 4 bits: attack rate */ + unsigned char decay; /* 4 bits: decay rate */ + unsigned char sustain; /* 4 bits: sustain level */ + unsigned char release; /* 4 bits: release rate */ + + unsigned char feedback; /* 3 bits: feedback for op0 */ + unsigned char connection; /* 0 for serial, 1 for parallel */ + unsigned char left; /* stereo left */ + unsigned char right; /* stereo right */ + unsigned char waveform; /* 3 bits: waveform shape */ +} snd_dm_fm_voice_t; + +typedef struct snd_dm_fm_note { + unsigned char voice; /* 0-17 voice channel */ + unsigned char octave; /* 3 bits: what octave to play */ + unsigned int fnum; /* 10 bits: frequency number */ + unsigned char key_on; /* set for active, clear for silent */ +} snd_dm_fm_note_t; + +typedef struct snd_dm_fm_params { + unsigned char am_depth; /* amplitude modulation depth (1=hi) */ + unsigned char vib_depth; /* vibrato depth (1=hi) */ + unsigned char kbd_split; /* keyboard split */ + unsigned char rhythm; /* percussion mode select */ + + /* This block is the percussion instrument data */ + unsigned char bass; + unsigned char snare; + unsigned char tomtom; + unsigned char cymbal; + unsigned char hihat; +} snd_dm_fm_params_t; + +#include +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SNDRV_LITTLE_ENDIAN +#elif __BYTE_ORDER == __BIG_ENDIAN +#define SNDRV_BIG_ENDIAN +#else +#error "Unsupported endian..." +#endif + +#include +#include + +struct sndrv_aes_iec958 { + unsigned char status[24]; /* AES/IEC958 channel status bits */ + unsigned char subcode[147]; /* AES/IEC958 subcode bits */ + unsigned char pad; /* nothing */ + unsigned char dig_subframe[4]; /* AES/IEC958 subframe bits */ +}; + +enum sndrv_hwdep_iface { + SNDRV_HWDEP_IFACE_OPL2 = 0, + SNDRV_HWDEP_IFACE_OPL3, + SNDRV_HWDEP_IFACE_OPL4, + SNDRV_HWDEP_IFACE_SB16CSP, /* Creative Signal Processor */ + SNDRV_HWDEP_IFACE_EMU10K1, /* FX8010 processor in EMU10K1 chip */ + SNDRV_HWDEP_IFACE_YSS225, /* Yamaha FX processor */ + SNDRV_HWDEP_IFACE_ICS2115, /* Wavetable synth */ + SNDRV_HWDEP_IFACE_SSCAPE, /* Ensoniq SoundScape ISA card (MC68EC000) */ + SNDRV_HWDEP_IFACE_VX, /* Digigram VX cards */ + SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */ + SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */ + SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */ + SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */ + SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */ + SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */ + SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */ + + /* Don't forget to change the following: */ + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC +}; + +struct sndrv_hwdep_info { + unsigned int device; /* WR: device number */ + int card; /* R: card number */ + unsigned char id[64]; /* ID (user selectable) */ + unsigned char name[80]; /* hwdep name */ + int iface; /* hwdep interface */ + unsigned char reserved[64]; /* reserved for future */ +}; + +/* generic DSP loader */ +struct sndrv_hwdep_dsp_status { + unsigned int version; /* R: driver-specific version */ + unsigned char id[32]; /* R: driver-specific ID string */ + unsigned int num_dsps; /* R: number of DSP images to transfer */ + unsigned int dsp_loaded; /* R: bit flags indicating the loaded DSPs */ + unsigned int chip_ready; /* R: 1 = initialization finished */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +struct sndrv_hwdep_dsp_image { + unsigned int index; /* W: DSP index */ + unsigned char name[64]; /* W: ID (e.g. file name) */ + unsigned char *image; /* W: binary image */ + size_t length; /* W: size of image in bytes */ + unsigned long driver_data; /* W: driver-specific data */ +}; + +typedef unsigned long sndrv_pcm_uframes_t; +typedef long sndrv_pcm_sframes_t; + +enum sndrv_pcm_class { + SNDRV_PCM_CLASS_GENERIC = 0, /* standard mono or stereo device */ + SNDRV_PCM_CLASS_MULTI, /* multichannel device */ + SNDRV_PCM_CLASS_MODEM, /* software modem class */ + SNDRV_PCM_CLASS_DIGITIZER, /* digitizer class */ + /* Don't forget to change the following: */ + SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER, +}; + +enum sndrv_pcm_subclass { + SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0, /* mono or stereo subdevices are mixed together */ + SNDRV_PCM_SUBCLASS_MULTI_MIX, /* multichannel subdevices are mixed together */ + /* Don't forget to change the following: */ + SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX, +}; + +enum sndrv_pcm_stream { + SNDRV_PCM_STREAM_PLAYBACK = 0, + SNDRV_PCM_STREAM_CAPTURE, + SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE, +}; + +enum sndrv_pcm_access { + SNDRV_PCM_ACCESS_MMAP_INTERLEAVED = 0, /* interleaved mmap */ + SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED, /* noninterleaved mmap */ + SNDRV_PCM_ACCESS_MMAP_COMPLEX, /* complex mmap */ + SNDRV_PCM_ACCESS_RW_INTERLEAVED, /* readi/writei */ + SNDRV_PCM_ACCESS_RW_NONINTERLEAVED, /* readn/writen */ + SNDRV_PCM_ACCESS_LAST = SNDRV_PCM_ACCESS_RW_NONINTERLEAVED, +}; + +enum sndrv_pcm_format { + SNDRV_PCM_FORMAT_S8 = 0, + SNDRV_PCM_FORMAT_U8, + SNDRV_PCM_FORMAT_S16_LE, + SNDRV_PCM_FORMAT_S16_BE, + SNDRV_PCM_FORMAT_U16_LE, + SNDRV_PCM_FORMAT_U16_BE, + SNDRV_PCM_FORMAT_S24_LE, /* low three bytes */ + SNDRV_PCM_FORMAT_S24_BE, /* low three bytes */ + SNDRV_PCM_FORMAT_U24_LE, /* low three bytes */ + SNDRV_PCM_FORMAT_U24_BE, /* low three bytes */ + SNDRV_PCM_FORMAT_S32_LE, + SNDRV_PCM_FORMAT_S32_BE, + SNDRV_PCM_FORMAT_U32_LE, + SNDRV_PCM_FORMAT_U32_BE, + SNDRV_PCM_FORMAT_FLOAT_LE, /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ + SNDRV_PCM_FORMAT_FLOAT_BE, /* 4-byte float, IEEE-754 32-bit, range -1.0 to 1.0 */ + SNDRV_PCM_FORMAT_FLOAT64_LE, /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ + SNDRV_PCM_FORMAT_FLOAT64_BE, /* 8-byte float, IEEE-754 64-bit, range -1.0 to 1.0 */ + SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE, /* IEC-958 subframe, Little Endian */ + SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, /* IEC-958 subframe, Big Endian */ + SNDRV_PCM_FORMAT_MU_LAW, + SNDRV_PCM_FORMAT_A_LAW, + SNDRV_PCM_FORMAT_IMA_ADPCM, + SNDRV_PCM_FORMAT_MPEG, + SNDRV_PCM_FORMAT_GSM, + SNDRV_PCM_FORMAT_SPECIAL = 31, + SNDRV_PCM_FORMAT_S24_3LE = 32, /* in three bytes */ + SNDRV_PCM_FORMAT_S24_3BE, /* in three bytes */ + SNDRV_PCM_FORMAT_U24_3LE, /* in three bytes */ + SNDRV_PCM_FORMAT_U24_3BE, /* in three bytes */ + SNDRV_PCM_FORMAT_S20_3LE, /* in three bytes */ + SNDRV_PCM_FORMAT_S20_3BE, /* in three bytes */ + SNDRV_PCM_FORMAT_U20_3LE, /* in three bytes */ + SNDRV_PCM_FORMAT_U20_3BE, /* in three bytes */ + SNDRV_PCM_FORMAT_S18_3LE, /* in three bytes */ + SNDRV_PCM_FORMAT_S18_3BE, /* in three bytes */ + SNDRV_PCM_FORMAT_U18_3LE, /* in three bytes */ + SNDRV_PCM_FORMAT_U18_3BE, /* in three bytes */ + SNDRV_PCM_FORMAT_LAST = SNDRV_PCM_FORMAT_U18_3BE, + +#ifdef SNDRV_LITTLE_ENDIAN + SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_LE, + SNDRV_PCM_FORMAT_U16 = SNDRV_PCM_FORMAT_U16_LE, + SNDRV_PCM_FORMAT_S24 = SNDRV_PCM_FORMAT_S24_LE, + SNDRV_PCM_FORMAT_U24 = SNDRV_PCM_FORMAT_U24_LE, + SNDRV_PCM_FORMAT_S32 = SNDRV_PCM_FORMAT_S32_LE, + SNDRV_PCM_FORMAT_U32 = SNDRV_PCM_FORMAT_U32_LE, + SNDRV_PCM_FORMAT_FLOAT = SNDRV_PCM_FORMAT_FLOAT_LE, + SNDRV_PCM_FORMAT_FLOAT64 = SNDRV_PCM_FORMAT_FLOAT64_LE, + SNDRV_PCM_FORMAT_IEC958_SUBFRAME = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE, +#endif +#ifdef SNDRV_BIG_ENDIAN + SNDRV_PCM_FORMAT_S16 = SNDRV_PCM_FORMAT_S16_BE, + SNDRV_PCM_FORMAT_U16 = SNDRV_PCM_FORMAT_U16_BE, + SNDRV_PCM_FORMAT_S24 = SNDRV_PCM_FORMAT_S24_BE, + SNDRV_PCM_FORMAT_U24 = SNDRV_PCM_FORMAT_U24_BE, + SNDRV_PCM_FORMAT_S32 = SNDRV_PCM_FORMAT_S32_BE, + SNDRV_PCM_FORMAT_U32 = SNDRV_PCM_FORMAT_U32_BE, + SNDRV_PCM_FORMAT_FLOAT = SNDRV_PCM_FORMAT_FLOAT_BE, + SNDRV_PCM_FORMAT_FLOAT64 = SNDRV_PCM_FORMAT_FLOAT64_BE, + SNDRV_PCM_FORMAT_IEC958_SUBFRAME = SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE, +#endif +}; + +enum sndrv_pcm_subformat { + SNDRV_PCM_SUBFORMAT_STD = 0, + SNDRV_PCM_SUBFORMAT_LAST = SNDRV_PCM_SUBFORMAT_STD, +}; + +enum sndrv_pcm_state { + SNDRV_PCM_STATE_OPEN = 0, /* stream is open */ + SNDRV_PCM_STATE_SETUP, /* stream has a setup */ + SNDRV_PCM_STATE_PREPARED, /* stream is ready to start */ + SNDRV_PCM_STATE_RUNNING, /* stream is running */ + SNDRV_PCM_STATE_XRUN, /* stream reached an xrun */ + SNDRV_PCM_STATE_DRAINING, /* stream is draining */ + SNDRV_PCM_STATE_PAUSED, /* stream is paused */ + SNDRV_PCM_STATE_SUSPENDED, /* hardware is suspended */ + SNDRV_PCM_STATE_DISCONNECTED, /* hardware is disconnected */ + SNDRV_PCM_STATE_LAST = SNDRV_PCM_STATE_DISCONNECTED, +}; + +enum { + SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000, + SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000, + SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000, +}; + +union sndrv_pcm_sync_id { + unsigned char id[16]; + unsigned short id16[8]; + unsigned int id32[4]; +}; + +struct sndrv_pcm_info { + unsigned int device; /* RO/WR (control): device number */ + unsigned int subdevice; /* RO/WR (control): subdevice number */ + int stream; /* RO/WR (control): stream number */ + int card; /* R: card number */ + unsigned char id[64]; /* ID (user selectable) */ + unsigned char name[80]; /* name of this device */ + unsigned char subname[32]; /* subdevice name */ + int dev_class; /* SNDRV_PCM_CLASS_* */ + int dev_subclass; /* SNDRV_PCM_SUBCLASS_* */ + unsigned int subdevices_count; + unsigned int subdevices_avail; + union sndrv_pcm_sync_id sync; /* hardware synchronization ID */ + unsigned char reserved[64]; /* reserved for future... */ +}; + +enum sndrv_pcm_hw_param { + SNDRV_PCM_HW_PARAM_ACCESS = 0, /* Access type */ + SNDRV_PCM_HW_PARAM_FIRST_MASK = SNDRV_PCM_HW_PARAM_ACCESS, + SNDRV_PCM_HW_PARAM_FORMAT, /* Format */ + SNDRV_PCM_HW_PARAM_SUBFORMAT, /* Subformat */ + SNDRV_PCM_HW_PARAM_LAST_MASK = SNDRV_PCM_HW_PARAM_SUBFORMAT, + + SNDRV_PCM_HW_PARAM_SAMPLE_BITS = 8, /* Bits per sample */ + SNDRV_PCM_HW_PARAM_FIRST_INTERVAL = SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + SNDRV_PCM_HW_PARAM_FRAME_BITS, /* Bits per frame */ + SNDRV_PCM_HW_PARAM_CHANNELS, /* Channels */ + SNDRV_PCM_HW_PARAM_RATE, /* Approx rate */ + SNDRV_PCM_HW_PARAM_PERIOD_TIME, /* Approx distance between interrupts + in us */ + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, /* Approx frames between interrupts */ + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, /* Approx bytes between interrupts */ + SNDRV_PCM_HW_PARAM_PERIODS, /* Approx interrupts per buffer */ + SNDRV_PCM_HW_PARAM_BUFFER_TIME, /* Approx duration of buffer in us */ + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, /* Size of buffer in frames */ + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, /* Size of buffer in bytes */ + SNDRV_PCM_HW_PARAM_TICK_TIME, /* Approx tick duration in us */ + SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME +}; + +struct sndrv_interval { + unsigned int min, max; + unsigned int openmin:1, + openmax:1, + integer:1, + empty:1; +}; + +struct sndrv_mask { + u_int32_t bits[(SNDRV_MASK_MAX+31)/32]; +}; + +struct sndrv_pcm_hw_params { + unsigned int flags; + struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - + SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; + struct sndrv_mask mres[5]; /* reserved masks */ + struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - + SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1]; + struct sndrv_interval ires[9]; /* reserved intervals */ + unsigned int rmask; /* W: requested masks */ + unsigned int cmask; /* R: changed masks */ + unsigned int info; /* R: Info flags for returned setup */ + unsigned int msbits; /* R: used most significant bits */ + unsigned int rate_num; /* R: rate numerator */ + unsigned int rate_den; /* R: rate denominator */ + sndrv_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ + unsigned char reserved[64]; /* reserved for future */ +}; + +enum sndrv_pcm_tstamp { + SNDRV_PCM_TSTAMP_NONE = 0, + SNDRV_PCM_TSTAMP_MMAP, + SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_MMAP, +}; + +struct sndrv_pcm_sw_params { + int tstamp_mode; /* timestamp mode */ + unsigned int period_step; + unsigned int sleep_min; /* min ticks to sleep */ + sndrv_pcm_uframes_t avail_min; /* min avail frames for wakeup */ + sndrv_pcm_uframes_t xfer_align; /* xfer size need to be a multiple */ + sndrv_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */ + sndrv_pcm_uframes_t stop_threshold; /* min avail frames for automatic stop */ + sndrv_pcm_uframes_t silence_threshold; /* min distance from noise for silence filling */ + sndrv_pcm_uframes_t silence_size; /* silence block size */ + sndrv_pcm_uframes_t boundary; /* pointers wrap point */ + unsigned char reserved[64]; /* reserved for future */ +}; + +struct sndrv_pcm_channel_info { + unsigned int channel; + long int offset; /* mmap offset */ + unsigned int first; /* offset to first sample in bits */ + unsigned int step; /* samples distance in bits */ +}; + +struct sndrv_pcm_status { + int state; /* stream state */ + struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */ + struct timespec tstamp; /* reference timestamp */ + sndrv_pcm_uframes_t appl_ptr; /* appl ptr */ + sndrv_pcm_uframes_t hw_ptr; /* hw ptr */ + sndrv_pcm_sframes_t delay; /* current delay in frames */ + sndrv_pcm_uframes_t avail; /* number of frames available */ + sndrv_pcm_uframes_t avail_max; /* max frames available on hw since last status */ + sndrv_pcm_uframes_t overrange; /* count of ADC (capture) overrange detections from last status */ + int suspended_state; /* suspended stream state */ + unsigned char reserved[60]; /* must be filled with zero */ +}; + +struct sndrv_pcm_mmap_status { + int state; /* RO: state - SNDRV_PCM_STATE_XXXX */ + int pad1; /* Needed for 64 bit alignment */ + sndrv_pcm_uframes_t hw_ptr; /* RO: hw ptr (0...boundary-1) */ + struct timespec tstamp; /* Timestamp */ + int suspended_state; /* RO: suspended stream state */ +}; + +struct sndrv_pcm_mmap_control { + sndrv_pcm_uframes_t appl_ptr; /* RW: appl ptr (0...boundary-1) */ + sndrv_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */ +}; + +struct sndrv_pcm_sync_ptr { + unsigned int flags; + union { + struct sndrv_pcm_mmap_status status; + unsigned char reserved[64]; + } s; + union { + struct sndrv_pcm_mmap_control control; + unsigned char reserved[64]; + } c; +}; + +struct sndrv_xferi { + sndrv_pcm_sframes_t result; + void *buf; + sndrv_pcm_uframes_t frames; +}; + +struct sndrv_xfern { + sndrv_pcm_sframes_t result; + void **bufs; + sndrv_pcm_uframes_t frames; +}; + +enum sndrv_rawmidi_stream { + SNDRV_RAWMIDI_STREAM_OUTPUT = 0, + SNDRV_RAWMIDI_STREAM_INPUT, + SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT, +}; + +struct sndrv_rawmidi_info { + unsigned int device; /* RO/WR (control): device number */ + unsigned int subdevice; /* RO/WR (control): subdevice number */ + int stream; /* WR: stream */ + int card; /* R: card number */ + unsigned int flags; /* SNDRV_RAWMIDI_INFO_XXXX */ + unsigned char id[64]; /* ID (user selectable) */ + unsigned char name[80]; /* name of device */ + unsigned char subname[32]; /* name of active or selected subdevice */ + unsigned int subdevices_count; + unsigned int subdevices_avail; + unsigned char reserved[64]; /* reserved for future use */ +}; + +struct sndrv_rawmidi_params { + int stream; + size_t buffer_size; /* queue size in bytes */ + size_t avail_min; /* minimum avail bytes for wakeup */ + unsigned int no_active_sensing: 1; /* do not send active sensing byte in close() */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +struct sndrv_rawmidi_status { + int stream; + struct timespec tstamp; /* Timestamp */ + size_t avail; /* available bytes */ + size_t xruns; /* count of overruns since last status (in bytes) */ + unsigned char reserved[16]; /* reserved for future use */ +}; + +enum sndrv_timer_class { + SNDRV_TIMER_CLASS_NONE = -1, + SNDRV_TIMER_CLASS_SLAVE = 0, + SNDRV_TIMER_CLASS_GLOBAL, + SNDRV_TIMER_CLASS_CARD, + SNDRV_TIMER_CLASS_PCM, + SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM, +}; + +/* slave timer classes */ +enum sndrv_timer_slave_class { + SNDRV_TIMER_SCLASS_NONE = 0, + SNDRV_TIMER_SCLASS_APPLICATION, + SNDRV_TIMER_SCLASS_SEQUENCER, /* alias */ + SNDRV_TIMER_SCLASS_OSS_SEQUENCER, /* alias */ + SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER, +}; + +struct sndrv_timer_ginfo { + struct sndrv_timer_id tid; /* requested timer ID */ + unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ + int card; /* card number */ + unsigned char id[64]; /* timer identification */ + unsigned char name[80]; /* timer name */ + unsigned long reserved0; /* reserved for future use */ + unsigned long resolution; /* average period resolution in ns */ + unsigned long resolution_min; /* minimal period resolution in ns */ + unsigned long resolution_max; /* maximal period resolution in ns */ + unsigned int clients; /* active timer clients */ + unsigned char reserved[32]; +}; + +struct sndrv_timer_gparams { + struct sndrv_timer_id tid; /* requested timer ID */ + unsigned long period_num; /* requested precise period duration (in seconds) - numerator */ + unsigned long period_den; /* requested precise period duration (in seconds) - denominator */ + unsigned char reserved[32]; +}; + +struct sndrv_timer_gstatus { + struct sndrv_timer_id tid; /* requested timer ID */ + unsigned long resolution; /* current period resolution in ns */ + unsigned long resolution_num; /* precise current period resolution (in seconds) - numerator */ + unsigned long resolution_den; /* precise current period resolution (in seconds) - denominator */ + unsigned char reserved[32]; +}; + +struct sndrv_timer_select { + struct sndrv_timer_id id; /* bind to timer ID */ + unsigned char reserved[32]; /* reserved */ +}; + +struct sndrv_timer_info { + unsigned int flags; /* timer flags - SNDRV_TIMER_FLG_* */ + int card; /* card number */ + unsigned char id[64]; /* timer identificator */ + unsigned char name[80]; /* timer name */ + unsigned long reserved0; /* reserved for future use */ + unsigned long resolution; /* average period resolution in ns */ + unsigned char reserved[64]; /* reserved */ +}; + +struct sndrv_timer_params { + unsigned int flags; /* flags - SNDRV_MIXER_PSFLG_* */ + unsigned int ticks; /* requested resolution in ticks */ + unsigned int queue_size; /* total size of queue (32-1024) */ + unsigned int reserved0; /* reserved, was: failure locations */ + unsigned int filter; /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ + unsigned char reserved[60]; /* reserved */ +}; + +struct sndrv_timer_status { + struct timespec tstamp; /* Timestamp - last update */ + unsigned int resolution; /* current period resolution in ns */ + unsigned int lost; /* counter of master tick lost */ + unsigned int overrun; /* count of read queue overruns */ + unsigned int queue; /* used queue size */ + unsigned char reserved[64]; /* reserved */ +}; + +struct sndrv_timer_read { + unsigned int resolution; + unsigned int ticks; +}; + +enum sndrv_timer_event { + SNDRV_TIMER_EVENT_RESOLUTION = 0, /* val = resolution in ns */ + SNDRV_TIMER_EVENT_TICK, /* val = ticks */ + SNDRV_TIMER_EVENT_START, /* val = resolution in ns */ + SNDRV_TIMER_EVENT_STOP, /* val = 0 */ + SNDRV_TIMER_EVENT_CONTINUE, /* val = resolution in ns */ + SNDRV_TIMER_EVENT_PAUSE, /* val = 0 */ + SNDRV_TIMER_EVENT_EARLY, /* val = 0, early event */ + SNDRV_TIMER_EVENT_SUSPEND, /* val = 0 */ + SNDRV_TIMER_EVENT_RESUME, /* val = resolution in ns */ + /* master timer events for slave timer instances */ + SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10, + SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10, + SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10, + SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10, + SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10, + SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10, +}; + +struct sndrv_timer_tread { + int event; + struct timespec tstamp; + unsigned int val; +}; + +struct sndrv_ctl_card_info { + int card; /* card number */ + int pad; /* reserved for future (was type) */ + unsigned char id[16]; /* ID of card (user selectable) */ + unsigned char driver[16]; /* Driver name */ + unsigned char name[32]; /* Short name of soundcard */ + unsigned char longname[80]; /* name + info text about soundcard */ + unsigned char reserved_[16]; /* reserved for future (was ID of mixer) */ + unsigned char mixername[80]; /* visual mixer identification */ + unsigned char components[80]; /* card components / fine identification, delimited with one space (AC97 etc..) */ + unsigned char reserved[48]; /* reserved for future */ +}; + +enum sndrv_ctl_elem_type { + SNDRV_CTL_ELEM_TYPE_NONE = 0, /* invalid */ + SNDRV_CTL_ELEM_TYPE_BOOLEAN, /* boolean type */ + SNDRV_CTL_ELEM_TYPE_INTEGER, /* integer type */ + SNDRV_CTL_ELEM_TYPE_ENUMERATED, /* enumerated type */ + SNDRV_CTL_ELEM_TYPE_BYTES, /* byte array */ + SNDRV_CTL_ELEM_TYPE_IEC958, /* IEC958 (S/PDIF) setup */ + SNDRV_CTL_ELEM_TYPE_INTEGER64, /* 64-bit integer type */ + SNDRV_CTL_ELEM_TYPE_LAST = SNDRV_CTL_ELEM_TYPE_INTEGER64, +}; + +enum sndrv_ctl_elem_iface { + SNDRV_CTL_ELEM_IFACE_CARD = 0, /* global control */ + SNDRV_CTL_ELEM_IFACE_HWDEP, /* hardware dependent device */ + SNDRV_CTL_ELEM_IFACE_MIXER, /* virtual mixer device */ + SNDRV_CTL_ELEM_IFACE_PCM, /* PCM device */ + SNDRV_CTL_ELEM_IFACE_RAWMIDI, /* RawMidi device */ + SNDRV_CTL_ELEM_IFACE_TIMER, /* timer device */ + SNDRV_CTL_ELEM_IFACE_SEQUENCER, /* sequencer client */ + SNDRV_CTL_ELEM_IFACE_LAST = SNDRV_CTL_ELEM_IFACE_SEQUENCER, +}; + +struct sndrv_ctl_elem_id { + unsigned int numid; /* numeric identifier, zero = invalid */ + int iface; /* interface identifier */ + unsigned int device; /* device/client number */ + unsigned int subdevice; /* subdevice (substream) number */ + unsigned char name[44]; /* ASCII name of item */ + unsigned int index; /* index of item */ +}; + +struct sndrv_ctl_elem_list { + unsigned int offset; /* W: first element ID to get */ + unsigned int space; /* W: count of element IDs to get */ + unsigned int used; /* R: count of element IDs set */ + unsigned int count; /* R: count of all elements */ + struct sndrv_ctl_elem_id *pids; /* R: IDs */ + unsigned char reserved[50]; +}; + +struct sndrv_ctl_elem_info { + struct sndrv_ctl_elem_id id; /* W: element ID */ + int type; /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ + unsigned int access; /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ + unsigned int count; /* count of values */ + pid_t owner; /* owner's PID of this control */ + union { + struct { + long min; /* R: minimum value */ + long max; /* R: maximum value */ + long step; /* R: step (0 variable) */ + } integer; + struct { + long long min; /* R: minimum value */ + long long max; /* R: maximum value */ + long long step; /* R: step (0 variable) */ + } integer64; + struct { + unsigned int items; /* R: number of items */ + unsigned int item; /* W: item number */ + char name[64]; /* R: value name */ + } enumerated; + unsigned char reserved[128]; + } value; + union { + unsigned short d[4]; /* dimensions */ + unsigned short *d_ptr; /* indirect */ + } dimen; + unsigned char reserved[64-4*sizeof(unsigned short)]; +}; + +struct sndrv_ctl_elem_value { + struct sndrv_ctl_elem_id id; /* W: element ID */ + unsigned int indirect: 1; /* W: use indirect pointer (xxx_ptr member) */ + union { + union { + long value[128]; + long *value_ptr; + } integer; + union { + long long value[64]; + long long *value_ptr; + } integer64; + union { + unsigned int item[128]; + unsigned int *item_ptr; + } enumerated; + union { + unsigned char data[512]; + unsigned char *data_ptr; + } bytes; + struct sndrv_aes_iec958 iec958; + } value; /* RO */ + struct timespec tstamp; + unsigned char reserved[128-sizeof(struct timespec)]; +}; + +struct sndrv_ctl_tlv { + unsigned int numid; /* control element numeric identification */ + unsigned int length; /* in bytes aligned to 4 */ + unsigned int tlv[0]; /* first TLV */ +}; + +enum sndrv_ctl_event_type { + SNDRV_CTL_EVENT_ELEM = 0, + SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM, +}; + +struct sndrv_ctl_event { + int type; /* event type - SNDRV_CTL_EVENT_* */ + union { + struct { + unsigned int mask; + struct sndrv_ctl_elem_id id; + } elem; + unsigned char data8[60]; + } data; +}; + +struct sndrv_xferv { + const struct iovec *vector; + unsigned long count; +}; + +typedef struct { + unsigned int internal_tram_size; /* in samples */ + unsigned int external_tram_size; /* in samples */ + char fxbus_names[16][32]; /* names of FXBUSes */ + char extin_names[16][32]; /* names of external inputs */ + char extout_names[32][32]; /* names of external outputs */ + unsigned int gpr_controls; /* count of GPR controls */ +} emu10k1_fx8010_info_t; + +enum emu10k1_ctl_elem_iface { + EMU10K1_CTL_ELEM_IFACE_MIXER = 2, /* virtual mixer device */ + EMU10K1_CTL_ELEM_IFACE_PCM = 3, /* PCM device */ +}; + +typedef struct { + unsigned int pad; /* don't use */ + int iface; /* interface identifier */ + unsigned int device; /* device/client number */ + unsigned int subdevice; /* subdevice (substream) number */ + unsigned char name[44]; /* ASCII name of item */ + unsigned int index; /* index of item */ +} emu10k1_ctl_elem_id_t; + +typedef struct { + emu10k1_ctl_elem_id_t id; /* full control ID definition */ + unsigned int vcount; /* visible count */ + unsigned int count; /* count of GPR (1..16) */ + unsigned short gpr[32]; /* GPR number(s) */ + unsigned int value[32]; /* initial values */ + unsigned int min; /* minimum range */ + unsigned int max; /* maximum range */ + unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ + unsigned int *tlv; +} emu10k1_fx8010_control_gpr_t; + +typedef struct { + char name[128]; + + unsigned long gpr_valid[0x200/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */ + uint32_t *gpr_map; /* initializers */ + + unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */ + emu10k1_fx8010_control_gpr_t *gpr_add_controls; /* GPR controls to add/replace */ + + unsigned int gpr_del_control_count; /* count of GPR controls to remove */ + emu10k1_ctl_elem_id_t *gpr_del_controls; /* IDs of GPR controls to remove */ + + unsigned int gpr_list_control_count; /* count of GPR controls to list */ + unsigned int gpr_list_control_total; /* total count of GPR controls */ + emu10k1_fx8010_control_gpr_t *gpr_list_controls; /* listed GPR controls */ + + unsigned long tram_valid[0x100/(sizeof(unsigned long)*8)]; /* bitmask of valid initializers */ + uint32_t *tram_data_map; /* data initializers */ + uint32_t *tram_addr_map; /* map initializers */ + + unsigned long code_valid[1024/(sizeof(unsigned long)*8)]; /* bitmask of valid instructions */ + uint32_t *code; /* one instruction - 64 bits */ +} emu10k1_fx8010_code_t; + +typedef struct { + unsigned int address; /* 31.bit == 1 -> external TRAM */ + unsigned int size; /* size in samples (4 bytes) */ + unsigned int *samples; /* pointer to samples (20-bit) */ + /* NULL->clear memory */ +} emu10k1_fx8010_tram_t; + +typedef struct { + unsigned int substream; /* substream number */ + unsigned int res1; /* reserved */ + unsigned int channels; /* 16-bit channels count, zero = remove this substream */ + unsigned int tram_start; /* ring buffer position in TRAM (in samples) */ + unsigned int buffer_size; /* count of buffered samples */ + unsigned short gpr_size; /* GPR containing size of ringbuffer in samples (host) */ + unsigned short gpr_ptr; /* GPR containing current pointer in the ring buffer (host = reset, FX8010) */ + unsigned short gpr_count; /* GPR containing count of samples between two interrupts (host) */ + unsigned short gpr_tmpcount; /* GPR containing current count of samples to interrupt (host = set, FX8010) */ + unsigned short gpr_trigger; /* GPR containing trigger (activate) information (host) */ + unsigned short gpr_running; /* GPR containing info if PCM is running (FX8010) */ + unsigned char pad; /* reserved */ + unsigned char etram[32]; /* external TRAM address & data (one per channel) */ + unsigned int res2; /* reserved */ +} emu10k1_fx8010_pcm_t; + +typedef enum { + Digiface, + Multiface, + H9652, + H9632, + Undefined, +} HDSP_IO_Type; + +typedef struct _snd_hdsp_peak_rms hdsp_peak_rms_t; + +struct _snd_hdsp_peak_rms { + uint32_t input_peaks[26]; + uint32_t playback_peaks[26]; + uint32_t output_peaks[28]; + uint64_t input_rms[26]; + uint64_t playback_rms[26]; + /* These are only used for H96xx cards */ + uint64_t output_rms[26]; +}; + +typedef struct _snd_hdsp_config_info hdsp_config_info_t; + +struct _snd_hdsp_config_info { + unsigned char pref_sync_ref; + unsigned char wordclock_sync_check; + unsigned char spdif_sync_check; + unsigned char adatsync_sync_check; + unsigned char adat_sync_check[3]; + unsigned char spdif_in; + unsigned char spdif_out; + unsigned char spdif_professional; + unsigned char spdif_emphasis; + unsigned char spdif_nonaudio; + unsigned int spdif_sample_rate; + unsigned int system_sample_rate; + unsigned int autosync_sample_rate; + unsigned char system_clock_mode; + unsigned char clock_source; + unsigned char autosync_ref; + unsigned char line_out; + unsigned char passthru; + unsigned char da_gain; + unsigned char ad_gain; + unsigned char phone_gain; + unsigned char xlr_breakout_cable; + unsigned char analog_extension_board; +}; + +typedef struct _snd_hdsp_firmware hdsp_firmware_t; + +struct _snd_hdsp_firmware { + void *firmware_data; /* 24413 x 4 bytes */ +}; + +typedef struct _snd_hdsp_version hdsp_version_t; + +struct _snd_hdsp_version { + HDSP_IO_Type io_type; + unsigned short firmware_rev; +}; + +typedef struct _snd_hdsp_mixer hdsp_mixer_t; + +struct _snd_hdsp_mixer { + unsigned short matrix[HDSP_MATRIX_MIXER_SIZE]; +}; + +typedef struct _snd_hdsp_9632_aeb hdsp_9632_aeb_t; + +struct _snd_hdsp_9632_aeb { + int aebi; + int aebo; +}; + +typedef struct snd_sb_csp_mc_header { + char codec_name[16]; /* id name of codec */ + unsigned short func_req; /* requested function */ +} snd_sb_csp_mc_header_t; + +typedef struct snd_sb_csp_microcode { + snd_sb_csp_mc_header_t info; + unsigned char data[SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE]; +} snd_sb_csp_microcode_t; + +typedef struct snd_sb_csp_start { + int sample_width; /* sample width, look above */ + int channels; /* channels, look above */ +} snd_sb_csp_start_t; + +typedef struct snd_sb_csp_info { + char codec_name[16]; /* id name of codec */ + unsigned short func_nr; /* function number */ + unsigned int acc_format; /* accepted PCM formats */ + unsigned short acc_channels; /* accepted channels */ + unsigned short acc_width; /* accepted sample width */ + unsigned short acc_rates; /* accepted sample rates */ + unsigned short csp_mode; /* CSP mode, see above */ + unsigned short run_channels; /* current channels */ + unsigned short run_width; /* current sample width */ + unsigned short version; /* version id: 0x10 - 0x1f */ + unsigned short state; /* state bits */ +} snd_sb_csp_info_t; + +struct sscape_bootblock +{ + unsigned char code[256]; + unsigned version; +}; + +struct sscape_microcode +{ + unsigned char *code; +}; diff --git a/linux-user/mmap.c b/linux-user/mmap.c index c4371d943a..d202e453f6 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -22,6 +22,7 @@ #include "qemu.h" #include "qemu-common.h" +#include "tcg.h" #include "translate-all.h" //#define DEBUG_MMAP @@ -33,6 +34,7 @@ void mmap_lock(void) { if (mmap_lock_count++ == 0) { pthread_mutex_lock(&mmap_mutex); + tcg_lock(); } } @@ -40,6 +42,7 @@ void mmap_unlock(void) { if (--mmap_lock_count == 0) { pthread_mutex_unlock(&mmap_mutex); + tcg_unlock(); } } @@ -357,6 +360,9 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) } } +#define SNDRV_PCM_MMAP_OFFSET_STATUS 0x80000000 +#define SNDRV_PCM_MMAP_OFFSET_CONTROL 0x81000000 + /* NOTE: all the constants are the HOST ones */ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, int flags, int fd, abi_ulong offset) @@ -391,6 +397,17 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, } #endif + /* Alsa tries to communcate with the kernel via mmap. This usually + * is a good idea when user- and kernelspace are running on the + * same architecture but does not work out when not. To make alsa + * not to use mmap, we can just have it fail on the mmap calls that + * would initiate this. + */ + if(offset == SNDRV_PCM_MMAP_OFFSET_STATUS || offset == SNDRV_PCM_MMAP_OFFSET_CONTROL) { + errno = EINVAL; + return -1; + } + if (offset & ~TARGET_PAGE_MASK) { errno = EINVAL; goto fail; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index bef465de4d..dab3b6a2bc 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -193,10 +193,10 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src, void target_set_brk(abi_ulong new_brk); abi_long do_brk(abi_ulong new_brk); void syscall_init(void); -abi_long do_syscall(void *cpu_env, int num, abi_long arg1, - abi_long arg2, abi_long arg3, abi_long arg4, - abi_long arg5, abi_long arg6, abi_long arg7, - abi_long arg8); +abi_long do_syscall(void *cpu_env, int num, abi_ulong arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, + abi_ulong arg5, abi_ulong arg6, abi_ulong arg7, + abi_ulong arg8); void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); extern THREAD CPUState *thread_cpu; void cpu_loop(CPUArchState *env); diff --git a/linux-user/signal.c b/linux-user/signal.c index 9a4d894e3a..2a070431b2 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -526,6 +526,10 @@ static void QEMU_NORETURN force_sig(int target_sig) trace_user_force_sig(env, target_sig, host_sig); gdb_signalled(env, target_sig); + if (target_sig == 6) { + goto no_core; + } + /* dump core if supported by target binary format */ if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) { stop_all_tasks(); @@ -543,6 +547,8 @@ static void QEMU_NORETURN force_sig(int target_sig) target_sig, strsignal(host_sig), "core dumped" ); } +no_core: + /* The proper exit code for dying from an uncaught signal is * -. The kernel doesn't allow exit() or _exit() to pass * a negative value. To get the proper exit code we need to diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 833f853200..cbb5085462 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4651,6 +4651,11 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp, uint32_t outbufsz; int free_fm = 0; + if (1) { + /* XXX agraf: fiemap breaks for me */ + return -TARGET_EINVAL; + } + assert(arg_type[0] == TYPE_PTR); assert(ie->access == IOC_RW); arg_type++; @@ -5179,7 +5184,12 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) ie = ioctl_entries; for(;;) { if (ie->target_cmd == 0) { - gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); + int i; + gemu_log("Unsupported ioctl: cmd=0x%04lx (%x)\n", (unsigned long)cmd, (unsigned int)(cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT); + for (i = 0; ioctl_entries[i].target_cmd; i++) { + if ((ioctl_entries[i].target_cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) == (cmd & ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT))) + gemu_log("%p\t->\t%s (%x)\n", (void *)(unsigned long)ioctl_entries[i].host_cmd, ioctl_entries[i].name, (ioctl_entries[i].target_cmd & (TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) >> TARGET_IOC_SIZESHIFT); + } return -TARGET_ENOSYS; } if (ie->target_cmd == cmd) @@ -5207,6 +5217,11 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) arg_type++; target_size = thunk_type_size(arg_type, 0); switch(ie->access) { + /* FIXME: actually the direction given in the ioctl should be + * correct so we can assume the communication is uni-directional. + * The alsa developers did not like this concept though and + * declared ioctls IOC_R and IOC_W even though they were IOC_RW.*/ +/* case IOC_R: ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp)); if (!is_error(ret)) { @@ -5225,6 +5240,7 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg) unlock_user(argptr, arg, 0); ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp)); break; +*/ default: case IOC_RW: argptr = lock_user(VERIFY_READ, arg, target_size, 1); @@ -5844,6 +5860,15 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, if (nptl_flags & CLONE_SETTLS) cpu_set_tls (new_env, newtls); + /* agraf: Pin ourselves to a single CPU when running multi-threaded. + This turned out to improve stability for me. */ + { + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(0, &mask); + sched_setaffinity(0, sizeof(mask), &mask); + } + /* Grab a mutex so that thread setup appears atomic. */ pthread_mutex_lock(&clone_lock); @@ -6967,6 +6992,25 @@ static int open_self_stat(void *cpu_env, int fd) return 0; } +static int open_cpuinfo(void *cpu_env, int fd) +{ + dprintf(fd, +"Processor : ARMv7 Processor rev 5 (v7l)\n" +"BogoMIPS : 799.53\n" +"Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3\n" +"CPU implementer : 0x41\n" +"CPU architecture: 7\n" +"CPU variant : 0x2\n" +"CPU part : 0xc08\n" +"CPU revision : 5\n" +"\n" +"Hardware : Genesi Efika MX (Smarttop)\n" +"Revision : 51030\n" +"Serial : 0000000000000000\n"); + + return 0; +} + static int open_self_auxv(void *cpu_env, int fd) { CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); @@ -7081,6 +7125,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) { "/proc/net/route", open_net_route, is_proc }, #endif + { "cpuinfo", open_cpuinfo, is_proc_myself }, { NULL, NULL, NULL } }; @@ -7149,10 +7194,10 @@ static target_timer_t get_timer_id(abi_long arg) /* do_syscall() should always have a single exit point at the end so that actions, such as logging of syscall results, can be performed. All errnos that do_syscall() returns must be -TARGET_. */ -abi_long do_syscall(void *cpu_env, int num, abi_long arg1, - abi_long arg2, abi_long arg3, abi_long arg4, - abi_long arg5, abi_long arg6, abi_long arg7, - abi_long arg8) +abi_long do_syscall(void *cpu_env, int num, abi_ulong arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, + abi_ulong arg5, abi_ulong arg6, abi_ulong arg7, + abi_ulong arg8) { CPUState *cpu = ENV_GET_CPU(cpu_env); abi_long ret; @@ -7510,9 +7555,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_oldstat: goto unimplemented; #endif - case TARGET_NR_lseek: - ret = get_errno(lseek(arg1, arg2, arg3)); + case TARGET_NR_lseek: { + off_t off = arg2; + if (arg3 != SEEK_SET) { + off = (abi_long)arg2; + } + ret = get_errno(lseek(arg1, off, arg3)); break; + } #if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA) /* Alpha specific */ case TARGET_NR_getxpid: @@ -8379,6 +8429,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_gettimeofday: { struct timeval tv; + if(copy_from_user_timeval(&tv, arg1)) + goto efault; ret = get_errno(gettimeofday(&tv, NULL)); if (!is_error(ret)) { if (copy_to_user_timeval(arg1, &tv)) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 783565463f..d31541d7d7 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2502,6 +2502,9 @@ struct target_f_owner_ex { #define TARGET_MTIOCGET TARGET_IOR('m', 2, struct mtget) #define TARGET_MTIOCPOS TARGET_IOR('m', 3, struct mtpos) +#define TARGET_FS_IOC_GETFLAGS TARGET_IORU('f', 1) +#define TARGET_FS_IOC_SETFLAGS TARGET_IOWU('f', 2) + struct target_sysinfo { abi_long uptime; /* Seconds since boot */ abi_ulong loads[3]; /* 1, 5, and 15 minute load averages */ @@ -2591,6 +2594,8 @@ struct target_ucred { uint32_t gid; }; +#include "ioctls_alsa_structs.h" + typedef int32_t target_timer_t; #define TARGET_SIGEV_MAX_SIZE 64 diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index af79fbf1de..4d99a9dd8b 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -83,6 +83,11 @@ STRUCT(buffmem_desc, STRUCT(mixer_info, MK_ARRAY(TYPE_CHAR, 16), MK_ARRAY(TYPE_CHAR, 32), TYPE_INT, MK_ARRAY(TYPE_INT, 10)) +/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */ +#ifdef __powerpc__ +#include "syscall_types_alsa.h" +#endif + /* loop device ioctls */ STRUCT(loop_info, TYPE_INT, /* lo_number */ diff --git a/linux-user/syscall_types_alsa.h b/linux-user/syscall_types_alsa.h new file mode 100644 index 0000000000..72622ae9a2 --- /dev/null +++ b/linux-user/syscall_types_alsa.h @@ -0,0 +1,1336 @@ +/* + * Advanced Linux Sound Architecture + * + * This program is free software, you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY, without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * aTYPE_LONG, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +STRUCT (sndrv_pcm_sframes, TYPE_LONG) +STRUCT (sndrv_seq_event_type, TYPE_CHAR) +STRUCT (sndrv_seq_instr_cluster, TYPE_INT) +STRUCT (sndrv_seq_position, TYPE_INT) +STRUCT (sndrv_seq_frequency, TYPE_INT) +STRUCT (sndrv_seq_tick_time, TYPE_INT) +STRUCT (sndrv_seq_instr_size, TYPE_INT) +STRUCT (sndrv_pcm_uframes, TYPE_ULONG) + + +STRUCT (timespec, + TYPE_LONG, + TYPE_LONG + ) + +STRUCT( fm_operator, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT(fm_instrument, + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_CHAR, /* instrument type */ + + MK_ARRAY(MK_STRUCT(STRUCT_fm_operator), 4), + MK_ARRAY(TYPE_CHAR, 2), + + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( fm_xoperator, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( fm_xinstrument, + TYPE_INT, /* structure type */ + + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_CHAR, /* instrument type */ + + MK_ARRAY(MK_STRUCT(STRUCT_fm_xoperator), 4), /* fm operators */ + MK_ARRAY(TYPE_CHAR, 2), + + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( gf1_wave, + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_INT, /* wave format */ + + TYPE_INT, /* some other ID for this instrument */ + TYPE_INT, /* begin of waveform in onboard memory */ + TYPE_PTRVOID, /* poTYPE_INTer to waveform in system memory */ + + TYPE_INT, /* size of waveform in samples */ + TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_SHORT, /* loop repeat - 0 = forever */ + + TYPE_CHAR, /* GF1 patch flags */ + TYPE_CHAR, + TYPE_INT, /* sample rate in Hz */ + TYPE_INT, /* low frequency range */ + TYPE_INT, /* high frequency range */ + TYPE_INT, /* root frequency range */ + TYPE_SHORT, + TYPE_CHAR, + MK_ARRAY(TYPE_CHAR, 6), + MK_ARRAY(TYPE_CHAR, 6), + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_SHORT, + TYPE_SHORT, /* 0-2048 or 0-2 */ + + TYPE_PTRVOID +) + +STRUCT(gf1_instrument, + TYPE_SHORT, + TYPE_SHORT, /* 0 - none, 1-65535 */ + + TYPE_CHAR, /* effect 1 */ + TYPE_CHAR, /* 0-127 */ + TYPE_CHAR, /* effect 2 */ + TYPE_CHAR, /* 0-127 */ + + TYPE_PTRVOID /* first waveform */ +) + +STRUCT( gf1_xwave, + TYPE_INT, /* structure type */ + + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_INT, /* wave format */ + + TYPE_INT, /* size of waveform in samples */ + TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_SHORT, /* loop repeat - 0 = forever */ + + TYPE_CHAR, /* GF1 patch flags */ + TYPE_CHAR, + TYPE_INT, /* sample rate in Hz */ + TYPE_INT, /* low frequency range */ + TYPE_INT, /* high frequency range */ + TYPE_INT, /* root frequency range */ + TYPE_SHORT, + TYPE_CHAR, + MK_ARRAY(TYPE_CHAR, 6), + MK_ARRAY(TYPE_CHAR, 6), + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_SHORT, + TYPE_SHORT /* 0-2048 or 0-2 */ +) + +STRUCT( gf1_xinstrument, + TYPE_INT, + + TYPE_SHORT, + TYPE_SHORT, /* 0 - none, 1-65535 */ + + TYPE_CHAR, /* effect 1 */ + TYPE_CHAR, /* 0-127 */ + TYPE_CHAR, /* effect 2 */ + TYPE_CHAR /* 0-127 */ +) + +STRUCT( gf1_info, + TYPE_CHAR, /* supported wave flags */ + MK_ARRAY(TYPE_CHAR, 3), + TYPE_INT, /* supported features */ + TYPE_INT, /* maximum 8-bit wave length */ + TYPE_INT /* maximum 16-bit wave length */ +) + +STRUCT( iwffff_wave, + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_INT, /* wave format */ + + TYPE_INT, /* some other ID for this wave */ + TYPE_INT, /* begin of waveform in onboard memory */ + TYPE_PTRVOID, /* poTYPE_INTer to waveform in system memory */ + + TYPE_INT, /* size of waveform in samples */ + TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_SHORT, /* loop repeat - 0 = forever */ + TYPE_INT, /* sample ratio (44100 * 1024 / rate) */ + TYPE_CHAR, /* 0 - 127 (no corresponding midi controller) */ + TYPE_CHAR, /* lower frequency range for this waveform */ + TYPE_CHAR, /* higher frequency range for this waveform */ + TYPE_CHAR, + + TYPE_PTRVOID +) + +STRUCT( iwffff_lfo, + TYPE_SHORT, /* (0-2047) 0.01Hz - 21.5Hz */ + TYPE_SHORT, /* volume +- (0-255) 0.48675dB/step */ + TYPE_SHORT, /* 0 - 950 deciseconds */ + TYPE_CHAR, /* see to IWFFFF_LFO_SHAPE_XXXX */ + TYPE_CHAR /* 0 - 255 deciseconds */ +) + +STRUCT( iwffff_env_point, + TYPE_SHORT, + TYPE_SHORT +) + +STRUCT( iwffff_env_record, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_CHAR, + TYPE_CHAR, + TYPE_PTRVOID +) + +STRUCT( iwffff_env, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_PTRVOID // MK_STRUCT(STRUCT_iwffff_env_record) +) + +STRUCT( iwffff_layer, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, /* range for layer based */ + TYPE_CHAR, /* on either velocity or frequency */ + TYPE_CHAR, /* pan offset from CC1 (0 left - 127 right) */ + TYPE_CHAR, /* position based on frequency (0-127) */ + TYPE_CHAR, /* 0-127 (no corresponding midi controller) */ + MK_STRUCT(STRUCT_iwffff_lfo), /* tremolo effect */ + MK_STRUCT(STRUCT_iwffff_lfo), /* vibrato effect */ + TYPE_SHORT, /* 0-2048, 1024 is equal to semitone scaling */ + TYPE_CHAR, /* center for keyboard frequency scaling */ + TYPE_CHAR, + MK_STRUCT(STRUCT_iwffff_env), /* pitch envelope */ + MK_STRUCT(STRUCT_iwffff_env), /* volume envelope */ + + TYPE_PTRVOID, // iwffff_wave_t *wave, + TYPE_PTRVOID // MK_STRUCT(STRUCT_iwffff_layer) +) + +STRUCT(iwffff_instrument, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, /* 0 - none, 1-65535 */ + + TYPE_CHAR, /* effect 1 */ + TYPE_CHAR, /* 0-127 */ + TYPE_CHAR, /* effect 2 */ + TYPE_CHAR, /* 0-127 */ + + TYPE_PTRVOID // iwffff_layer_t *layer, /* first layer */ +) + +STRUCT( iwffff_xwave, + TYPE_INT, /* structure type */ + + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + + TYPE_INT, /* wave format */ + TYPE_INT, /* offset to ROM (address) */ + + TYPE_INT, /* size of waveform in samples */ + TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_SHORT, /* loop repeat - 0 = forever */ + TYPE_INT, /* sample ratio (44100 * 1024 / rate) */ + TYPE_CHAR, /* 0 - 127 (no corresponding midi controller) */ + TYPE_CHAR, /* lower frequency range for this waveform */ + TYPE_CHAR, /* higher frequency range for this waveform */ + TYPE_CHAR +) + +STRUCT( iwffff_xlfo, + TYPE_SHORT, /* (0-2047) 0.01Hz - 21.5Hz */ + TYPE_SHORT, /* volume +- (0-255) 0.48675dB/step */ + TYPE_SHORT, /* 0 - 950 deciseconds */ + TYPE_CHAR, /* see to ULTRA_IW_LFO_SHAPE_XXXX */ + TYPE_CHAR /* 0 - 255 deciseconds */ +) + +STRUCT( iwffff_xenv_point, + TYPE_SHORT, + TYPE_SHORT +) + +STRUCT( iwffff_xenv_record, + TYPE_INT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( iwffff_xenv, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( iwffff_xlayer, + TYPE_INT, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, /* range for layer based */ + TYPE_CHAR, /* on either velocity or frequency */ + TYPE_CHAR, /* pan offset from CC1 (0 left - 127 right) */ + TYPE_CHAR, /* position based on frequency (0-127) */ + TYPE_CHAR, /* 0-127 (no corresponding midi controller) */ + MK_STRUCT(STRUCT_iwffff_xlfo), /* tremolo effect */ + MK_STRUCT(STRUCT_iwffff_xlfo), /* vibrato effect */ + TYPE_SHORT, /* 0-2048, 1024 is equal to semitone scaling */ + TYPE_CHAR, /* center for keyboard frequency scaling */ + TYPE_CHAR, + MK_STRUCT(STRUCT_iwffff_xenv), /* pitch envelope */ + MK_STRUCT(STRUCT_iwffff_xenv) /* volume envelope */ +) + +STRUCT( iwffff_xinstrument, + TYPE_INT, + + TYPE_SHORT, + TYPE_SHORT, + TYPE_SHORT, /* 0 - none, 1-65535 */ + + TYPE_CHAR, /* effect 1 */ + TYPE_CHAR, /* 0-127 */ + TYPE_CHAR, /* effect 2 */ + TYPE_CHAR /* 0-127 */ +) + +STRUCT(iwffff_rom_header, + MK_ARRAY(TYPE_CHAR, 8), + TYPE_CHAR, + TYPE_CHAR, + MK_ARRAY(TYPE_CHAR, 16), + MK_ARRAY(TYPE_CHAR, 10), + TYPE_SHORT, + TYPE_SHORT, + TYPE_INT, + MK_ARRAY(TYPE_CHAR, 128), + MK_ARRAY(TYPE_CHAR, 64), + MK_ARRAY(TYPE_CHAR, 128) +) + +STRUCT( iwffff_info, + TYPE_INT, /* supported format bits */ + TYPE_INT, /* supported effects (1 << IWFFFF_EFFECT*) */ + TYPE_INT, /* LFO effects */ + TYPE_INT, /* maximum 8-bit wave length */ + TYPE_INT /* maximum 16-bit wave length */ +) + +STRUCT( simple_instrument_info, + TYPE_INT, /* supported format bits */ + TYPE_INT, /* supported effects (1 << SIMPLE_EFFECT_*) */ + TYPE_INT, /* maximum 8-bit wave length */ + TYPE_INT /* maximum 16-bit wave length */ +) + +STRUCT(simple_instrument, + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_INT, /* wave format */ + + TYPE_INT, /* some other ID for this instrument */ + TYPE_INT, /* begin of waveform in onboard memory */ + TYPE_PTRVOID, /* poTYPE_INTer to waveform in system memory */ + + TYPE_INT, /* size of waveform in samples */ + TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop end offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_SHORT, /* loop repeat - 0 = forever */ + + TYPE_CHAR, /* effect 1 */ + TYPE_CHAR, /* 0-127 */ + TYPE_CHAR, /* effect 2 */ + TYPE_CHAR /* 0-127 */ +) + +STRUCT( simple_xinstrument, + TYPE_INT, + + MK_ARRAY(TYPE_INT, 4), /* share id - zero = no sharing */ + TYPE_INT, /* wave format */ + + TYPE_INT, /* size of waveform in samples */ + TYPE_INT, /* start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* bits loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_INT, /* loop start offset in samples * 16 (lowest 4 bits - fraction) */ + TYPE_SHORT, /* loop repeat - 0 = forever */ + + TYPE_CHAR, /* effect 1 */ + TYPE_CHAR, /* 0-127 */ + TYPE_CHAR, /* effect 2 */ + TYPE_CHAR /* 0-127 */ +) + +/** event address */ +STRUCT( sndrv_seq_addr, + TYPE_CHAR, /**< Client number: 0..255, 255 = broadcast to all clients */ + TYPE_CHAR /**< Port within client: 0..255, 255 = broadcast to all ports */ +) + +/** port connection */ +STRUCT( sndrv_seq_connect, + MK_STRUCT(STRUCT_sndrv_seq_addr), + MK_STRUCT(STRUCT_sndrv_seq_addr) +) + +STRUCT( sndrv_seq_ev_note, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, /* only for SNDRV_SEQ_EVENT_NOTE */ + TYPE_INT /* only for SNDRV_SEQ_EVENT_NOTE */ +) + + /* controller event */ +STRUCT( sndrv_seq_ev_ctrl, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, /* pad */ + TYPE_INT, + TYPE_INT +) + + /* generic set of bytes (12x8 bit) */ +STRUCT( sndrv_seq_ev_raw8, + MK_ARRAY(TYPE_CHAR, 12) /* 8 bit value */ +) + + /* generic set of TYPE_INTegers (3x32 bit) */ +STRUCT( sndrv_seq_ev_raw32, + MK_ARRAY(TYPE_INT, 3) /* 32 bit value */ +) + + /* external stored data */ +STRUCT( sndrv_seq_ev_ext, + TYPE_INT, /* length of data */ + TYPE_PTRVOID /* poTYPE_INTer to data (note: maybe 64-bit) */ +) + +/* Instrument type */ +STRUCT( sndrv_seq_instr, + TYPE_INT, + TYPE_INT, /* the upper byte means a private instrument (owner - client #) */ + TYPE_SHORT, + TYPE_SHORT +) + + /* sample number */ +STRUCT( sndrv_seq_ev_sample, + TYPE_INT, + TYPE_SHORT, + TYPE_SHORT +) + + /* sample cluster */ +STRUCT( sndrv_seq_ev_cluster, + TYPE_INT +) + + /* sample volume control, if any value is set to -1 == do not change */ +STRUCT( sndrv_seq_ev_volume, + TYPE_SHORT, /* range: 0-16383 */ + TYPE_SHORT, /* left-right balance, range: 0-16383 */ + TYPE_SHORT, /* front-rear balance, range: 0-16383 */ + TYPE_SHORT /* down-up balance, range: 0-16383 */ +) + + /* simple loop redefinition */ +STRUCT( sndrv_seq_ev_loop, + TYPE_INT, /* loop start (in samples) * 16 */ + TYPE_INT /* loop end (in samples) * 16 */ +) + +STRUCT( sndrv_seq_ev_sample_control, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, /* pad */ + MK_ARRAY(TYPE_INT, 2) +) + + + +/* INSTR_BEGIN event */ +STRUCT( sndrv_seq_ev_instr_begin, + TYPE_INT +) + +STRUCT( sndrv_seq_result, + TYPE_INT, + TYPE_INT +) + + +STRUCT( sndrv_seq_real_time, + TYPE_INT, + TYPE_INT +) + +STRUCT( sndrv_seq_queue_skew, + TYPE_INT, + TYPE_INT +) + + /* queue timer control */ +STRUCT( sndrv_seq_ev_queue_control, + TYPE_CHAR, /* affected queue */ + MK_ARRAY(TYPE_CHAR, 3), /* reserved */ + MK_ARRAY(TYPE_INT, 2) +) + + /* quoted event - inside the kernel only */ +STRUCT( sndrv_seq_ev_quote, + MK_STRUCT(STRUCT_sndrv_seq_addr), /* original sender */ + TYPE_SHORT, /* optional data */ + MK_STRUCT(STRUCT_sndrv_seq_event) /* quoted event */ +) + + + /* sequencer event */ +STRUCT( sndrv_seq_event, + TYPE_CHAR, /* event type */ + TYPE_CHAR, /* event flags */ + TYPE_CHAR, + + TYPE_CHAR, /* schedule queue */ + MK_STRUCT(STRUCT_sndrv_seq_real_time), /* schedule time */ + + + MK_STRUCT(STRUCT_sndrv_seq_addr), /* source address */ + MK_STRUCT(STRUCT_sndrv_seq_addr), /* destination address */ + + MK_ARRAY(TYPE_INT,3) +) + + +/* + * bounce event - stored as variable size data + */ +STRUCT( sndrv_seq_event_bounce, + TYPE_INT, + MK_STRUCT(STRUCT_sndrv_seq_event) + /* external data follows here. */ +) + +STRUCT( sndrv_seq_system_info, + TYPE_INT, /* maximum queues count */ + TYPE_INT, /* maximum clients count */ + TYPE_INT, /* maximum ports per client */ + TYPE_INT, /* maximum channels per port */ + TYPE_INT, /* current clients */ + TYPE_INT, /* current queues */ + MK_ARRAY(TYPE_CHAR, 24) +) + +STRUCT( sndrv_seq_running_info, + TYPE_CHAR, /* client id */ + TYPE_CHAR, /* 1 = big-endian */ + TYPE_CHAR, + TYPE_CHAR, /* reserved */ + MK_ARRAY(TYPE_CHAR, 12) +) + +STRUCT( sndrv_seq_client_info, + TYPE_INT, /* client number to inquire */ + TYPE_INT, /* client type */ + MK_ARRAY(TYPE_CHAR, 64), /* client name */ + TYPE_INT, /* filter flags */ + MK_ARRAY(TYPE_CHAR, 8), /* multicast filter bitmap */ + MK_ARRAY(TYPE_CHAR, 32), /* event filter bitmap */ + TYPE_INT, /* RO: number of ports */ + TYPE_INT, /* number of lost events */ + MK_ARRAY(TYPE_CHAR, 64) /* for future use */ +) + +STRUCT( sndrv_seq_client_pool, + TYPE_INT, /* client number to inquire */ + TYPE_INT, /* outgoing (write) pool size */ + TYPE_INT, /* incoming (read) pool size */ + TYPE_INT, /* minimum free pool size for select/blocking mode */ + TYPE_INT, /* unused size */ + TYPE_INT, /* unused size */ + MK_ARRAY(TYPE_CHAR, 64) +) + +STRUCT( sndrv_seq_remove_events, + TYPE_INT, /* Flags that determine what gets removed */ + + MK_STRUCT(STRUCT_sndrv_seq_real_time), + + TYPE_CHAR, /* Queue for REMOVE_DEST */ + MK_STRUCT(STRUCT_sndrv_seq_addr), /* Address for REMOVE_DEST */ + TYPE_CHAR, /* Channel for REMOVE_DEST */ + + TYPE_INT, /* For REMOVE_EVENT_TYPE */ + TYPE_CHAR, /* Tag for REMOVE_TAG */ + + MK_ARRAY(TYPE_INT, 10) /* To allow for future binary compatibility */ + +) + +STRUCT( sndrv_seq_port_info, + MK_STRUCT(STRUCT_sndrv_seq_addr), /* client/port numbers */ + MK_ARRAY(TYPE_CHAR, 64), /* port name */ + + TYPE_INT, /* port capability bits */ + TYPE_INT, /* port type bits */ + TYPE_INT, /* channels per MIDI port */ + TYPE_INT, /* voices per MIDI port */ + TYPE_INT, /* voices per SYNTH port */ + + TYPE_INT, /* R/O: subscribers for output (from this port) */ + TYPE_INT, /* R/O: subscribers for input (to this port) */ + + TYPE_PTRVOID, /* reserved for kernel use (must be NULL) */ + TYPE_INT, /* misc. conditioning */ + TYPE_CHAR, /* queue # for timestamping */ + MK_ARRAY(TYPE_CHAR, 59) /* for future use */ +) + +STRUCT( sndrv_seq_queue_info, + TYPE_INT, /* queue id */ + + /* + * security settings, only owner of this queue can start/stop timer + * etc. if the queue is locked for other clients + */ + TYPE_INT, /* client id for owner of the queue */ + TYPE_INT, /* timing queue locked for other queues */ + MK_ARRAY(TYPE_CHAR, 64), /* name of this queue */ + TYPE_INT, /* flags */ + MK_ARRAY(TYPE_CHAR, 60) /* for future use */ + +) + +STRUCT( sndrv_seq_queue_status, + TYPE_INT, /* queue id */ + TYPE_INT, /* read-only - queue size */ + TYPE_INT, /* current tick */ + MK_STRUCT(STRUCT_sndrv_seq_real_time), /* current time */ + TYPE_INT, /* running state of queue */ + TYPE_INT, /* various flags */ + MK_ARRAY(TYPE_CHAR, 64) /* for the future */ +) + +STRUCT( sndrv_seq_queue_tempo, + TYPE_INT, /* sequencer queue */ + TYPE_INT, + TYPE_INT, + TYPE_INT, /* queue skew */ + TYPE_INT, /* queue skew base */ + MK_ARRAY(TYPE_CHAR, 24) /* for the future */ +) + +STRUCT( sndrv_timer_id, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_INT +) + +STRUCT( sndrv_seq_queue_timer, + TYPE_INT, /* sequencer queue */ + TYPE_INT, /* source timer type */ + MK_STRUCT(STRUCT_sndrv_timer_id), /* ALSA's timer ID */ + TYPE_INT, /* resolution in Hz */ + MK_ARRAY(TYPE_CHAR, 64) /* for the future use */ +) + +STRUCT( sndrv_seq_queue_client, + TYPE_INT, /* sequencer queue */ + TYPE_INT, /* sequencer client */ + TYPE_INT, /* queue is used with this client + (must be set for accepting events) */ + /* per client watermarks */ + MK_ARRAY(TYPE_CHAR, 64) /* for future use */ +) + +STRUCT( sndrv_seq_port_subscribe, + MK_STRUCT(STRUCT_sndrv_seq_addr), /* sender address */ + MK_STRUCT(STRUCT_sndrv_seq_addr), /* destination address */ + TYPE_INT, /* number of voices to be allocated (0 = don't care) */ + TYPE_INT, /* modes */ + TYPE_CHAR, /* input time-stamp queue (optional) */ + MK_ARRAY(TYPE_CHAR, 3), /* reserved */ + MK_ARRAY(TYPE_CHAR, 64) +) + +STRUCT( sndrv_seq_query_subs, + MK_STRUCT(STRUCT_sndrv_seq_addr), /* client/port id to be searched */ + TYPE_INT, /* READ or WRITE */ + TYPE_INT, /* 0..N-1 */ + TYPE_INT, /* R/O: number of subscriptions on this port */ + MK_STRUCT(STRUCT_sndrv_seq_addr), /* R/O: result */ + TYPE_CHAR, /* R/O: result */ + TYPE_INT, /* R/O: result */ + MK_ARRAY(TYPE_CHAR, 64) /* for future use */ +) + +STRUCT( sndrv_seq_instr_info, + TYPE_INT, /* operation result */ + MK_ARRAY(TYPE_INT, 8), /* bitmap of supported formats */ + TYPE_INT, /* count of RAM banks */ + MK_ARRAY(TYPE_INT, 16), /* size of RAM banks */ + TYPE_INT, /* count of ROM banks */ + MK_ARRAY(TYPE_INT, 8), /* size of ROM banks */ + MK_ARRAY(TYPE_CHAR, 128) +) + +STRUCT( sndrv_seq_instr_status, + TYPE_INT, /* operation result */ + MK_ARRAY(TYPE_INT, 16), /* free RAM in banks */ + TYPE_INT, /* count of downloaded instruments */ + MK_ARRAY(TYPE_CHAR, 128) +) + +STRUCT( sndrv_seq_instr_format_info, + MK_ARRAY(TYPE_CHAR, 16), /* format identifier - SNDRV_SEQ_INSTR_ID_* */ + TYPE_INT /* max data length (without this structure) */ +) + +STRUCT( sndrv_seq_instr_format_info_result, + TYPE_INT, /* operation result */ + MK_ARRAY(TYPE_CHAR, 16), /* format identifier */ + TYPE_INT /* filled data length (without this structure) */ +) + +STRUCT( sndrv_seq_instr_data, + MK_ARRAY(TYPE_CHAR, 32), /* instrument name */ + MK_ARRAY(TYPE_CHAR, 16), /* for the future use */ + TYPE_INT, /* instrument type */ + MK_STRUCT(STRUCT_sndrv_seq_instr), + MK_ARRAY(TYPE_CHAR, 4) /* fillup */ +) + +STRUCT( sndrv_seq_instr_header, + MK_STRUCT(STRUCT_sndrv_seq_instr), + TYPE_INT, /* get/put/free command */ + TYPE_INT, /* query flags (only for get) */ + TYPE_INT, /* real instrument data length (without header) */ + TYPE_INT, /* operation result */ + MK_ARRAY(TYPE_CHAR, 16), /* for the future */ + MK_STRUCT(STRUCT_sndrv_seq_instr_data) /* instrument data (for put/get result) */ +) + +STRUCT( sndrv_seq_instr_cluster_set, + TYPE_INT, /* cluster identifier */ + MK_ARRAY(TYPE_CHAR, 32), /* cluster name */ + TYPE_INT, /* cluster priority */ + MK_ARRAY(TYPE_CHAR, 64) /* for the future use */ +) + +STRUCT( sndrv_seq_instr_cluster_get, + TYPE_INT, /* cluster identifier */ + MK_ARRAY(TYPE_CHAR, 32), /* cluster name */ + TYPE_INT, /* cluster priority */ + MK_ARRAY(TYPE_CHAR, 64) /* for the future use */ +) + +STRUCT( snd_dm_fm_info, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( snd_dm_fm_voice, + TYPE_CHAR, /* operator cell (0 or 1) */ + TYPE_CHAR, /* FM voice (0 to 17) */ + + TYPE_CHAR, /* amplitude modulation */ + TYPE_CHAR, /* vibrato effect */ + TYPE_CHAR, /* sustain phase */ + TYPE_CHAR, /* keyboard scaling */ + TYPE_CHAR, /* 4 bits: harmonic and multiplier */ + TYPE_CHAR, /* 2 bits: decrease output freq rises */ + TYPE_CHAR, /* 6 bits: volume */ + + TYPE_CHAR, /* 4 bits: attack rate */ + TYPE_CHAR, /* 4 bits: decay rate */ + TYPE_CHAR, /* 4 bits: sustain level */ + TYPE_CHAR, /* 4 bits: release rate */ + + TYPE_CHAR, /* 3 bits: feedback for op0 */ + TYPE_CHAR, + TYPE_CHAR, /* stereo left */ + TYPE_CHAR, /* stereo right */ + TYPE_CHAR /* 3 bits: waveform shape */ +) + +STRUCT( snd_dm_fm_note, + TYPE_CHAR, /* 0-17 voice channel */ + TYPE_CHAR, /* 3 bits: what octave to play */ + TYPE_INT, /* 10 bits: frequency number */ + TYPE_CHAR +) + +STRUCT( snd_dm_fm_params, + TYPE_CHAR, /* amplitude modulation depth (1=hi) */ + TYPE_CHAR, /* vibrato depth (1=hi) */ + TYPE_CHAR, /* keyboard split */ + TYPE_CHAR, /* percussion mode select */ + + /* This block is the percussion instrument data */ + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( sndrv_aes_iec958, + MK_ARRAY(TYPE_CHAR, 24), /* AES/IEC958 channel status bits */ + MK_ARRAY(TYPE_CHAR, 147), /* AES/IEC958 subcode bits */ + TYPE_CHAR, /* nothing */ + MK_ARRAY(TYPE_CHAR, 4) /* AES/IEC958 subframe bits */ +) + +STRUCT( sndrv_hwdep_info, + TYPE_INT, /* WR: device number */ + TYPE_INT, /* R: card number */ + MK_ARRAY(TYPE_CHAR, 64), /* ID (user selectable) */ + MK_ARRAY(TYPE_CHAR, 80), /* hwdep name */ + TYPE_INT, /* hwdep interface */ + MK_ARRAY(TYPE_CHAR, 64) /* reserved for future */ +) + +/* generic DSP loader */ +STRUCT( sndrv_hwdep_dsp_status, + TYPE_INT, /* R: driver-specific version */ + MK_ARRAY(TYPE_CHAR, 32), /* R: driver-specific ID string */ + TYPE_INT, /* R: number of DSP images to transfer */ + TYPE_INT, /* R: bit flags indicating the loaded DSPs */ + TYPE_INT, /* R: 1 = initialization finished */ + MK_ARRAY(TYPE_CHAR, 16) /* reserved for future use */ +) + +STRUCT( sndrv_hwdep_dsp_image, + TYPE_INT, /* W: DSP index */ + MK_ARRAY(TYPE_CHAR, 64), /* W: ID (e.g. file name) */ + TYPE_CHAR, /* W: binary image */ + TYPE_LONG, /* W: size of image in bytes */ + TYPE_LONG /* W: driver-specific data */ +) + +STRUCT( sndrv_pcm_info, + TYPE_INT, /* RO/WR (control): device number */ + TYPE_INT, /* RO/WR (control): subdevice number */ + TYPE_INT, /* RO/WR (control): stream number */ + TYPE_INT, /* R: card number */ + MK_ARRAY(TYPE_CHAR, 64), /* ID (user selectable) */ + MK_ARRAY(TYPE_CHAR, 80), /* name of this device */ + MK_ARRAY(TYPE_CHAR, 32), /* subdevice name */ + TYPE_INT, /* SNDRV_PCM_CLASS_* */ + TYPE_INT, /* SNDRV_PCM_SUBCLASS_* */ + TYPE_INT, + TYPE_INT, + MK_ARRAY(TYPE_INT, 4), + + MK_ARRAY(TYPE_CHAR, 64) /* reserved for future... */ +) + +STRUCT( sndrv_interval, + TYPE_INT, + TYPE_INT, + TYPE_INTBITFIELD +) + +STRUCT( sndrv_mask, + MK_ARRAY(TYPE_INT, (SNDRV_MASK_MAX+31)/32) +) + +STRUCT( sndrv_pcm_hw_params, + TYPE_INT, + MK_ARRAY(MK_STRUCT(STRUCT_sndrv_mask),SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1), + MK_ARRAY(MK_STRUCT(STRUCT_sndrv_mask), 5), /* reserved masks */ + MK_ARRAY(MK_STRUCT(STRUCT_sndrv_interval), SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1), + MK_ARRAY(MK_STRUCT(STRUCT_sndrv_interval), 9), /* reserved intervals */ + TYPE_INT, /* W: requested masks */ + TYPE_INT, /* R: changed masks */ + TYPE_INT, /* R: Info flags for returned setup */ + TYPE_INT, /* R: used most significant bits */ + TYPE_INT, /* R: rate numerator */ + TYPE_INT, /* R: rate denominator */ + TYPE_LONG, /* R: chip FIFO size in frames */ + MK_ARRAY(TYPE_CHAR, 64) /* reserved for future */ +) + +STRUCT( sndrv_pcm_sw_params, + TYPE_INT, /* timestamp mode */ + TYPE_INT, + TYPE_INT, /* min ticks to sleep */ + TYPE_LONG, /* min avail frames for wakeup */ + TYPE_LONG, /* xfer size need to be a multiple */ + TYPE_LONG, /* min hw_avail frames for automatic start */ + TYPE_LONG, /* min avail frames for automatic stop */ + TYPE_LONG, /* min distance from noise for silence filling */ + TYPE_LONG, /* silence block size */ + TYPE_LONG, /* poTYPE_INTers wrap point */ + MK_ARRAY(TYPE_CHAR, 64) /* reserved for future */ +) + +STRUCT( sndrv_pcm_channel_info, + TYPE_INT, + TYPE_LONG, /* mmap offset (FIXME) */ + TYPE_INT, /* offset to first sample in bits */ + TYPE_INT /* samples distance in bits */ +) + + +STRUCT( sndrv_pcm_status, + TYPE_INT, /* stream state */ + MK_STRUCT(STRUCT_timespec), /* time when stream was started/stopped/paused */ + MK_STRUCT(STRUCT_timespec), /* reference timestamp */ + TYPE_LONG, /* appl ptr */ + TYPE_LONG, /* hw ptr */ + TYPE_LONG, /* current delay in frames */ + TYPE_LONG, /* number of frames available */ + TYPE_LONG, /* max frames available on hw since last status */ + TYPE_LONG, /* count of ADC (capture) overrange detections from last status */ + TYPE_INT, /* suspended stream state */ + MK_ARRAY(TYPE_CHAR, 60) /* must be filled with zero */ +) + +STRUCT( sndrv_pcm_mmap_status, + TYPE_INT, /* RO: state - SNDRV_PCM_STATE_XXXX */ + TYPE_INT, /* Needed for 64 bit alignment */ + TYPE_LONG, /* RO: hw ptr (0...boundary-1) */ + MK_STRUCT(STRUCT_timespec), /* Timestamp */ + TYPE_INT /* RO: suspended stream state */ +) + +STRUCT( sndrv_pcm_mmap_control, + TYPE_LONG, /* RW: appl ptr (0...boundary-1) */ + TYPE_LONG /* RW: min available frames for wakeup */ +) + +STRUCT( sndrv_pcm_sync_ptr, + TYPE_INT, + // FIXME: does not work with 64-bit target + MK_STRUCT(STRUCT_sndrv_pcm_mmap_status), // 28 bytes on 32-bit target + MK_ARRAY(TYPE_CHAR, 64 - 24), // so we pad to 64 bytes (was a union) + + MK_STRUCT(STRUCT_sndrv_pcm_mmap_control), // 8 bytes on 32-bit target + MK_ARRAY(TYPE_CHAR, 64 - 8) // so we pad to 64 bytes (was a union)) +) + +STRUCT( sndrv_xferi, + TYPE_LONG, + TYPE_PTRVOID, + TYPE_LONG +) + +STRUCT( sndrv_xfern, + TYPE_LONG, + TYPE_PTRVOID, + TYPE_LONG +) + +STRUCT( sndrv_rawmidi_info, + TYPE_INT, /* RO/WR (control): device number */ + TYPE_INT, /* RO/WR (control): subdevice number */ + TYPE_INT, /* WR: stream */ + TYPE_INT, /* R: card number */ + TYPE_INT, /* SNDRV_RAWMIDI_INFO_XXXX */ + MK_ARRAY(TYPE_CHAR, 64), /* ID (user selectable) */ + MK_ARRAY(TYPE_CHAR, 80), /* name of device */ + MK_ARRAY(TYPE_CHAR, 32), /* name of active or selected subdevice */ + TYPE_INT, + TYPE_INT, + MK_ARRAY(TYPE_CHAR, 64) /* reserved for future use */ +) + +STRUCT( sndrv_rawmidi_params, + TYPE_INT, + TYPE_LONG, /* queue size in bytes */ + TYPE_LONG, /* minimum avail bytes for wakeup */ + TYPE_INT, /* do not send active sensing byte in close() */ + MK_ARRAY(TYPE_CHAR, 16) /* reserved for future use */ +) + +STRUCT( sndrv_rawmidi_status, + TYPE_INT, + MK_STRUCT(STRUCT_timespec), /* Timestamp */ + TYPE_LONG, /* available bytes */ + TYPE_LONG, /* count of overruns since last status (in bytes) */ + MK_ARRAY(TYPE_CHAR, 16) /* reserved for future use */ +) + +STRUCT( sndrv_timer_ginfo, + MK_STRUCT(STRUCT_sndrv_timer_id), /* requested timer ID */ + TYPE_INT, /* timer flags - SNDRV_TIMER_FLG_* */ + TYPE_INT, /* card number */ + MK_ARRAY(TYPE_CHAR, 64), /* timer identification */ + MK_ARRAY(TYPE_CHAR, 80), /* timer name */ + TYPE_LONG, /* reserved for future use */ + TYPE_LONG, /* average period resolution in ns */ + TYPE_LONG, /* minimal period resolution in ns */ + TYPE_LONG, /* maximal period resolution in ns */ + TYPE_INT, /* active timer clients */ + MK_ARRAY(TYPE_CHAR, 32) +) + +STRUCT( sndrv_timer_gparams, + MK_STRUCT(STRUCT_sndrv_timer_id), /* requested timer ID */ + TYPE_LONG, /* requested precise period duration (in seconds) - numerator */ + TYPE_LONG, /* requested precise period duration (in seconds) - denominator */ + MK_ARRAY(TYPE_CHAR, 32) +) + +STRUCT( sndrv_timer_gstatus, + MK_STRUCT(STRUCT_sndrv_timer_id), /* requested timer ID */ + TYPE_LONG, /* current period resolution in ns */ + TYPE_LONG, /* precise current period resolution (in seconds) - numerator */ + TYPE_LONG, /* precise current period resolution (in seconds) - denominator */ + MK_ARRAY(TYPE_CHAR, 32) +) + +STRUCT( sndrv_timer_select, + MK_STRUCT(STRUCT_sndrv_timer_id), /* bind to timer ID */ + MK_ARRAY(TYPE_CHAR, 32) /* reserved */ +) + +STRUCT( sndrv_timer_info, + TYPE_INT, /* timer flags - SNDRV_TIMER_FLG_* */ + TYPE_INT, /* card number */ + MK_ARRAY(TYPE_CHAR, 64), /* timer identificator */ + MK_ARRAY(TYPE_CHAR, 80), /* timer name */ + TYPE_LONG, /* reserved for future use */ + TYPE_LONG, /* average period resolution in ns */ + MK_ARRAY(TYPE_CHAR, 64) /* reserved */ +) + +STRUCT( sndrv_timer_params, + TYPE_INT, /* flags - SNDRV_MIXER_PSFLG_* */ + TYPE_INT, /* requested resolution in ticks */ + TYPE_INT, /* total size of queue (32-1024) */ + TYPE_INT, + TYPE_INT, /* event filter (bitmask of SNDRV_TIMER_EVENT_*) */ + MK_ARRAY(TYPE_CHAR, 60) /* reserved */ +) + +STRUCT( sndrv_timer_status, + MK_STRUCT(STRUCT_timespec), /* Timestamp - last update */ + TYPE_INT, /* current period resolution in ns */ + TYPE_INT, /* counter of master tick lost */ + TYPE_INT, /* count of read queue overruns */ + TYPE_INT, /* used queue size */ + MK_ARRAY(TYPE_CHAR, 64) /* reserved */ +) + +STRUCT( sndrv_timer_read, + TYPE_INT, + TYPE_INT +) + +STRUCT( sndrv_timer_tread, + TYPE_INT, + MK_STRUCT(STRUCT_timespec), + TYPE_INT +) + +STRUCT( sndrv_ctl_card_info, + TYPE_INT, /* card number */ + TYPE_INT, /* reserved for future (was type) */ + MK_ARRAY(TYPE_CHAR, 16), /* ID of card (user selectable) */ + MK_ARRAY(TYPE_CHAR, 16), /* Driver name */ + MK_ARRAY(TYPE_CHAR, 32), /* Short name of soundcard */ + MK_ARRAY(TYPE_CHAR, 80), /* name + info text about soundcard */ + MK_ARRAY(TYPE_CHAR, 16), /* reserved for future (was ID of mixer) */ + MK_ARRAY(TYPE_CHAR, 80), /* visual mixer identification */ + MK_ARRAY(TYPE_CHAR, 80), /* card components / fine identification, delimited with one space (AC97 etc..) */ + MK_ARRAY(TYPE_CHAR, 48) /* reserved for future */ +) + +STRUCT( sndrv_ctl_elem_id, + TYPE_INT, + TYPE_INT, /* interface identifier */ + TYPE_INT, /* device/client number */ + TYPE_INT, /* subdevice (substream) number */ + MK_ARRAY(TYPE_CHAR, 44), /* ASCII name of item */ + TYPE_INT /* index of item */ +) + +STRUCT( sndrv_ctl_elem_list, + TYPE_INT, /* W: first element ID to get */ + TYPE_INT, /* W: count of element IDs to get */ + TYPE_INT, /* R: count of element IDs set */ + TYPE_INT, /* R: count of all elements */ + MK_STRUCT(STRUCT_sndrv_ctl_elem_id), /* R: IDs */ + MK_ARRAY(TYPE_CHAR, 50) +) + +STRUCT( sndrv_ctl_elem_info, + MK_STRUCT(STRUCT_sndrv_ctl_elem_id), /* W: element ID */ + TYPE_INT, /* R: value type - SNDRV_CTL_ELEM_TYPE_* */ + TYPE_INT, /* R: value access (bitmask) - SNDRV_CTL_ELEM_ACCESS_* */ + TYPE_INT, /* count of values */ + TYPE_INT, /* owner's PID of this control */ + MK_ARRAY(TYPE_CHAR, 128), // FIXME: prone to break (was union) + MK_ARRAY(TYPE_SHORT, 4), /* dimensions */ + MK_ARRAY(TYPE_CHAR, 64-4*sizeof(unsigned short)) +) + +STRUCT( sndrv_ctl_elem_value, + MK_STRUCT(STRUCT_sndrv_ctl_elem_id), /* W: element ID */ + TYPE_INT, /* W: use indirect pointer (xxx_ptr member) */ + MK_ARRAY(TYPE_INT, 128), + MK_STRUCT(STRUCT_timespec), + MK_ARRAY(TYPE_CHAR, 128-sizeof(struct timespec)) // FIXME: breaks on 64-bit host +) + +STRUCT( sndrv_ctl_tlv, + TYPE_INT, /* control element numeric identification */ + TYPE_INT, /* in bytes aligned to 4 */ + MK_ARRAY(TYPE_INT, 0) /* first TLV */ // FIXME: what is this supposed to become? +) + +STRUCT( sndrv_ctl_event, + TYPE_INT, /* event type - SNDRV_CTL_EVENT_* */ + TYPE_INT, + MK_STRUCT(STRUCT_sndrv_ctl_elem_id) // 64 bytes +) + +STRUCT( iovec, + TYPE_PTRVOID, + TYPE_LONG + ) + + +STRUCT( sndrv_xferv, + MK_STRUCT(STRUCT_iovec), + TYPE_LONG +) + +STRUCT(emu10k1_fx8010_info, + TYPE_INT, /* in samples */ + TYPE_INT, /* in samples */ + MK_ARRAY(MK_ARRAY(TYPE_CHAR, 32), 16), /* names of FXBUSes */ + MK_ARRAY(MK_ARRAY(TYPE_CHAR, 32), 16), /* names of external inputs */ + MK_ARRAY(MK_ARRAY(TYPE_CHAR, 32), 32), /* names of external outputs */ + TYPE_INT /* count of GPR controls */ +) + +STRUCT(emu10k1_ctl_elem_id, + TYPE_INT, /* don't use */ + TYPE_INT, /* interface identifier */ + TYPE_INT, /* device/client number */ + TYPE_INT, /* subdevice (substream) number */ + MK_ARRAY(TYPE_CHAR, 44), /* ASCII name of item */ + TYPE_INT /* index of item */ +) + +STRUCT(emu10k1_fx8010_control_gpr, + MK_STRUCT(STRUCT_emu10k1_ctl_elem_id), /* full control ID definition */ + TYPE_INT, /* visible count */ + TYPE_INT, /* count of GPR (1..16) */ + MK_ARRAY(TYPE_SHORT, 32), /* GPR number(s) */ + MK_ARRAY(TYPE_INT, 32), /* initial values */ + TYPE_INT, /* minimum range */ + TYPE_INT, /* maximum range */ + TYPE_INT, /* translation type (EMU10K1_GPR_TRANSLATION*) */ + TYPE_INT +) + +#ifndef TARGET_LONG_SIZE +#define TARGET_LONG_SIZE 4 +#endif + +STRUCT(emu10k1_fx8010_code, + MK_ARRAY(TYPE_CHAR, 128), + + MK_ARRAY(TYPE_LONG, 0x200/(TARGET_LONG_SIZE*8)), /* bitmask of valid initializers */ + TYPE_PTRVOID, /* initializers */ + + TYPE_INT, /* count of GPR controls to add/replace */ + MK_STRUCT(STRUCT_emu10k1_fx8010_control_gpr), /* GPR controls to add/replace */ + + TYPE_INT, /* count of GPR controls to remove */ + MK_STRUCT(STRUCT_emu10k1_ctl_elem_id), /* IDs of GPR controls to remove */ + + TYPE_INT, /* count of GPR controls to list */ + TYPE_INT, /* total count of GPR controls */ + MK_STRUCT(STRUCT_emu10k1_fx8010_control_gpr), /* listed GPR controls */ + + MK_ARRAY(TYPE_LONG, 0x100/(TARGET_LONG_SIZE*8)), /* bitmask of valid initializers */ + TYPE_PTRVOID, /* data initializers */ + TYPE_PTRVOID, /* map initializers */ + + MK_ARRAY(TYPE_LONG, 1024/(TARGET_LONG_SIZE*8)), /* bitmask of valid instructions */ + TYPE_PTRVOID /* one instruction - 64 bits */ +) + +STRUCT(emu10k1_fx8010_tram, + TYPE_INT, /* 31.bit == 1 -> external TRAM */ + TYPE_INT, /* size in samples (4 bytes) */ + TYPE_INT /* pointer to samples (20-bit) */ + /* NULL->clear memory */ +) + +STRUCT(emu10k1_fx8010_pcm, + TYPE_INT, /* substream number */ + TYPE_INT, /* reserved */ + TYPE_INT, + TYPE_INT, /* ring buffer position in TRAM (in samples) */ + TYPE_INT, /* count of buffered samples */ + TYPE_SHORT, /* GPR containing size of ringbuffer in samples (host) */ + TYPE_SHORT, + TYPE_SHORT, /* GPR containing count of samples between two TYPE_INTerrupts (host) */ + TYPE_SHORT, + TYPE_SHORT, /* GPR containing trigger (activate) information (host) */ + TYPE_SHORT, /* GPR containing info if PCM is running (FX8010) */ + TYPE_CHAR, /* reserved */ + MK_ARRAY(TYPE_CHAR, 32), /* external TRAM address & data (one per channel) */ + TYPE_INT /* reserved */ +) + +STRUCT( hdsp_peak_rms, + MK_ARRAY(TYPE_INT, 26), + MK_ARRAY(TYPE_INT, 26), + MK_ARRAY(TYPE_INT, 28), + MK_ARRAY(TYPE_LONGLONG, 26), + MK_ARRAY(TYPE_LONGLONG, 26), + /* These are only used for H96xx cards */ + MK_ARRAY(TYPE_LONGLONG, 26) +) + +STRUCT( hdsp_config_info, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + MK_ARRAY(TYPE_CHAR, 3), + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR, + TYPE_CHAR +) + +STRUCT( hdsp_firmware, + TYPE_PTRVOID /* 24413 x 4 bytes */ +) + +STRUCT( hdsp_version, + TYPE_INT, + TYPE_SHORT +) + +STRUCT( hdsp_mixer, + MK_ARRAY(TYPE_SHORT, HDSP_MATRIX_MIXER_SIZE) +) + +STRUCT( hdsp_9632_aeb, + TYPE_INT, + TYPE_INT +) + +STRUCT( snd_sb_csp_mc_header, + MK_ARRAY(TYPE_CHAR, 16), /* id name of codec */ + TYPE_SHORT /* requested function */ +) + +STRUCT( snd_sb_csp_microcode, + MK_STRUCT(STRUCT_snd_sb_csp_mc_header), + MK_ARRAY(TYPE_CHAR, SNDRV_SB_CSP_MAX_MICROCODE_FILE_SIZE) +) + +STRUCT( snd_sb_csp_start, + TYPE_INT, + TYPE_INT +) + +STRUCT( snd_sb_csp_info, + MK_ARRAY(TYPE_CHAR, 16), /* id name of codec */ + TYPE_SHORT, /* function number */ + TYPE_INT, /* accepted PCM formats */ + TYPE_SHORT, /* accepted channels */ + TYPE_SHORT, /* accepted sample width */ + TYPE_SHORT, /* accepted sample rates */ + TYPE_SHORT, + TYPE_SHORT, /* current channels */ + TYPE_SHORT, /* current sample width */ + TYPE_SHORT, /* version id: 0x10 - 0x1f */ + TYPE_SHORT /* state bits */ +) + +STRUCT( sscape_bootblock, + MK_ARRAY(TYPE_CHAR, 256), + TYPE_INT +) + +STRUCT( sscape_microcode, + TYPE_PTRVOID +) diff --git a/qemu-bridge-helper.c b/qemu-bridge-helper.c index 5396fbfbb6..f3710b80a3 100644 --- a/qemu-bridge-helper.c +++ b/qemu-bridge-helper.c @@ -110,7 +110,12 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) *argend = 0; if (strcmp(cmd, "deny") == 0) { - acl_rule = g_malloc(sizeof(*acl_rule)); + acl_rule = calloc(1, sizeof(*acl_rule)); + if (!acl_rule) { + fclose(f); + errno = ENOMEM; + return -1; + } if (strcmp(arg, "all") == 0) { acl_rule->type = ACL_DENY_ALL; } else { @@ -119,7 +124,12 @@ static int parse_acl_file(const char *filename, ACLList *acl_list) } QSIMPLEQ_INSERT_TAIL(acl_list, acl_rule, entry); } else if (strcmp(cmd, "allow") == 0) { - acl_rule = g_malloc(sizeof(*acl_rule)); + acl_rule = calloc(1, sizeof(*acl_rule)); + if (!acl_rule) { + fclose(f); + errno = ENOMEM; + return -1; + } if (strcmp(arg, "all") == 0) { acl_rule->type = ACL_ALLOW_ALL; } else { @@ -413,6 +423,17 @@ int main(int argc, char **argv) goto cleanup; } +#ifndef CONFIG_LIBCAP + /* avoid sending the fd as root user if running suid to not fool + * peer credentials to daemons that dont expect that + */ + if (setuid(getuid()) < 0) { + fprintf(stderr, "Failed to drop privileges.\n"); + ret = EXIT_FAILURE; + goto cleanup; + } +#endif + /* write fd to the domain socket */ if (send_fd(unixfd, fd) == -1) { fprintf(stderr, "failed to write fd to unix socket: %s\n", @@ -434,7 +455,7 @@ cleanup: } while ((acl_rule = QSIMPLEQ_FIRST(&acl_list)) != NULL) { QSIMPLEQ_REMOVE_HEAD(&acl_list, entry); - g_free(acl_rule); + free(acl_rule); } return ret; diff --git a/qemu-char.c b/qemu-char.c index 8a0ab05a7b..bc0bee34ce 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -510,6 +510,9 @@ typedef struct { IOEventHandler *chr_event[MAX_MUX]; void *ext_opaque[MAX_MUX]; CharDriverState *drv; +#if defined(TARGET_S390X) + QEMUTimer *accept_timer; +#endif int focus; int mux_cnt; int term_got_escape; @@ -669,6 +672,15 @@ static void mux_chr_accept_input(CharDriverState *chr) d->chr_read[m](d->ext_opaque[m], &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); } + +#if defined(TARGET_S390X) + /* We're still not able to sync producer and consumer, so let's wait a bit + and try again by then. */ + if (d->prod[m] != d->cons[m]) { + qemu_mod_timer(d->accept_timer, qemu_get_clock_ns(vm_clock) + + (int64_t)100000); + } +#endif } static int mux_chr_can_read(void *opaque) @@ -817,6 +829,10 @@ static CharDriverState *qemu_chr_open_mux(const char *id, chr->opaque = d; d->drv = drv; d->focus = -1; +#if defined(TARGET_S390X) + d->accept_timer = qemu_new_timer_ns(vm_clock, + (QEMUTimerCB*)mux_chr_accept_input, chr); +#endif chr->chr_close = mux_chr_close; chr->chr_write = mux_chr_write; chr->chr_update_read_handler = mux_chr_update_read_handler; diff --git a/qemu-options.hx b/qemu-options.hx index a71aaf8ea8..7f3206923a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3132,6 +3132,16 @@ Store the QEMU process PID in @var{file}. It is useful if you launch QEMU from a script. ETEXI +DEF("nooutgoing", HAS_ARG, QEMU_OPTION_nooutgoing, \ + "-nooutgoing \n" \ + " incoming traffic only from IP, no outgoing\n", \ + QEMU_ARCH_ALL) +STEXI +@item -nooutgoing +Forbid userspace networking to make outgoing connections. Only accept incoming +connections from ip address IP. +ETEXI + DEF("singlestep", 0, QEMU_OPTION_singlestep, \ "-singlestep always run in singlestep mode\n", QEMU_ARCH_ALL) STEXI diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh index de4d1c13d4..3affcdca1b 100755 --- a/scripts/qemu-binfmt-conf.sh +++ b/scripts/qemu-binfmt-conf.sh @@ -201,7 +201,7 @@ qemu_check_systemd() { } qemu_generate_register() { - echo ":qemu-$cpu:M::$magic:$mask:$qemu:$FLAGS" + echo ":qemu-$cpu:M::$magic:$mask:$qemu:P$FLAGS" } qemu_register_interpreter() { @@ -242,9 +242,9 @@ qemu_set_binfmts() { continue fi - qemu="$QEMU_PATH/qemu-$cpu" + qemu="$QEMU_PATH/qemu-$cpu-binfmt" if [ "$cpu" = "i486" ] ; then - qemu="$QEMU_PATH/qemu-i386" + qemu="$QEMU_PATH/qemu-i386-binfmt" fi if [ "$host_family" != "$family" ] ; then @@ -259,7 +259,7 @@ BINFMT_SET=qemu_register_interpreter SYSTEMDDIR="/etc/binfmt.d" DEBIANDIR="/usr/share/binfmts" -QEMU_PATH=/usr/local/bin +QEMU_PATH=/usr/bin FLAGS="" options=$(getopt -o ds:Q:e:hc: -l debian,systemd:,qemu-path:,exportdir:,help,credential: -- "$@") diff --git a/slirp/socket.c b/slirp/socket.c index 280050a21f..4fe68bb76a 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -608,6 +608,8 @@ sorecvfrom(struct socket *so) } /* if ping packet */ } +extern int slirp_nooutgoing; + /* * sendto() a socket */ @@ -625,6 +627,12 @@ sosendto(struct socket *so, struct mbuf *m) DEBUG_CALL(" sendto()ing)"); sotranslate_out(so, &addr); + /* Only allow DNS requests */ + if (slirp_nooutgoing && ntohs(((struct sockaddr_in *)&addr)->sin_port) != 53) { + errno = EHOSTUNREACH; + return -1; + } + /* Don't care what port we get */ ret = sendto(so->s, m->m_data, m->m_len, 0, (struct sockaddr *)&addr, sockaddr_size(&addr)); diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index ed16e1807f..b2c7a8cba0 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -391,6 +391,8 @@ tcp_sockclosed(struct tcpcb *tp) * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ +extern int slirp_nooutgoing; + int tcp_fconnect(struct socket *so, unsigned short af) { int ret=0; @@ -398,6 +400,11 @@ int tcp_fconnect(struct socket *so, unsigned short af) DEBUG_CALL("tcp_fconnect"); DEBUG_ARG("so = %p", so); + if (slirp_nooutgoing) { + errno = EHOSTUNREACH; + return -1; + } + ret = so->s = qemu_socket(af, SOCK_STREAM, 0); if (ret >= 0) { int opt, s=so->s; @@ -478,6 +485,11 @@ void tcp_connect(struct socket *inso) tcp_close(sototcpcb(so)); /* This will sofree() as well */ return; } + if (slirp_nooutgoing && ((struct sockaddr_in *)&addr)->sin_addr.s_addr != slirp_nooutgoing) { + tcp_close(sototcpcb(so)); /* This will sofree() as well */ + closesocket(s); + return; + } qemu_set_nonblock(s); socket_set_fast_reuse(s); opt = 1; diff --git a/tcg/tcg.c b/tcg/tcg.c index 42417bdc92..ef6ae1011d 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -33,6 +33,8 @@ #include "qemu/cutils.h" #include "qemu/host-utils.h" #include "qemu/timer.h" +#include "config-host.h" +#include "qemu/thread.h" /* Note: the long term plan is to reduce the dependencies on the QEMU CPU definitions. Currently they are used for qemu_ld/st @@ -120,6 +122,29 @@ static bool tcg_out_tb_finalize(TCGContext *s); static TCGRegSet tcg_target_available_regs[2]; static TCGRegSet tcg_target_call_clobber_regs; +#ifdef CONFIG_USER_ONLY +static __thread int tcg_lock_count; +#endif +void tcg_lock(void) +{ +#ifdef CONFIG_USER_ONLY + TCGContext *s = &tcg_ctx; + if (tcg_lock_count++ == 0) { + qemu_mutex_lock(&s->lock); + } +#endif +} + +void tcg_unlock(void) +{ +#ifdef CONFIG_USER_ONLY + TCGContext *s = &tcg_ctx; + if (--tcg_lock_count == 0) { + qemu_mutex_unlock(&s->lock); + } +#endif +} + #if TCG_TARGET_INSN_UNIT_SIZE == 1 static __attribute__((unused)) inline void tcg_out8(TCGContext *s, uint8_t v) { @@ -332,6 +357,7 @@ void tcg_context_init(TCGContext *s) memset(s, 0, sizeof(*s)); s->nb_globals = 0; + qemu_mutex_init(&s->lock); /* Count total number of arguments and allocate the corresponding space */ @@ -2551,6 +2577,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) qemu_log("\n"); } #endif + tcg_lock(); #ifdef CONFIG_PROFILER s->opt_time -= profile_getclock(); @@ -2673,6 +2700,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) the buffer completely. Thus we can test for overflow after generating code without having to check during generation. */ if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) { + tcg_unlock(); return -1; } } @@ -2686,6 +2714,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) /* flush instruction cache */ flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr); + tcg_unlock(); return tcg_current_code_size(s); } diff --git a/tcg/tcg.h b/tcg/tcg.h index 1bcabcad9d..5c2522e50e 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -29,6 +29,7 @@ #include "cpu.h" #include "exec/tb-context.h" #include "qemu/bitops.h" +#include "qemu/thread.h" #include "tcg-target.h" /* XXX: make safe guess about sizes */ @@ -697,6 +698,8 @@ struct TCGContext { uint16_t gen_insn_end_off[TCG_MAX_INSNS]; target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS]; + + QemuMutex lock; }; extern TCGContext tcg_ctx; @@ -904,6 +907,9 @@ TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *op, TCGOpcode opc, int narg); void tcg_optimize(TCGContext *s); +extern void tcg_lock(void); +extern void tcg_unlock(void); + /* only used for debugging purposes */ void tcg_dump_ops(TCGContext *s); diff --git a/thread-pool.c b/thread-pool.c index 6fba913529..ee0b485f07 100644 --- a/thread-pool.c +++ b/thread-pool.c @@ -297,7 +297,12 @@ static void thread_pool_init_one(ThreadPool *pool, AioContext *ctx) qemu_mutex_init(&pool->lock); qemu_cond_init(&pool->worker_stopped); qemu_sem_init(&pool->sem, 0); - pool->max_threads = 64; + if (sizeof(pool) == 4) { + /* 32bit systems run out of virtual memory quickly */ + pool->max_threads = 4; + } else { + pool->max_threads = 64; + } pool->new_thread_bh = aio_bh_new(ctx, spawn_thread_bh_fn, pool); QLIST_INIT(&pool->head); diff --git a/thunk.c b/thunk.c index 2dac36666d..0eb72861fe 100644 --- a/thunk.c +++ b/thunk.c @@ -37,6 +37,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr) case TYPE_CHAR: case TYPE_SHORT: case TYPE_INT: + case TYPE_INTBITFIELD: case TYPE_LONGLONG: case TYPE_ULONGLONG: case TYPE_LONG: @@ -139,6 +140,26 @@ const argtype *thunk_convert(void *dst, const void *src, case TYPE_INT: *(uint32_t *)dst = tswap32(*(uint32_t *)src); break; + case TYPE_INTBITFIELD: +#if defined(TARGET_I386) && defined(__powerpc__) + /* powerpc uses the MSB, whereas i386 uses the LSB + * to store the first bit in a field */ + { + unsigned char byte = *(uint8_t *)src; + *(uint8_t *)dst = ((byte >> 7) & 1) + | ((byte >> 5) & 2) + | ((byte >> 3) & 4) + | ((byte >> 1) & 8) + | ((byte << 1) & 16) + | ((byte << 3) & 32) + | ((byte << 5) & 64) + | ((byte << 7) & 128); + /* FIXME: implement for bitfields > 1 byte and other archs */ + } +#else + *(uint32_t *)dst = tswap32(*(uint32_t *)src); +#endif + break; case TYPE_LONGLONG: case TYPE_ULONGLONG: *(uint64_t *)dst = tswap64(*(uint64_t *)src); diff --git a/translate-all.c b/translate-all.c index efeba298b9..8c8805618b 100644 --- a/translate-all.c +++ b/translate-all.c @@ -767,17 +767,21 @@ static TranslationBlock *tb_alloc(target_ulong pc) { TranslationBlock *tb; + tcg_lock(); if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks) { + tcg_unlock(); return NULL; } tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++]; tb->pc = pc; tb->cflags = 0; + tcg_unlock(); return tb; } void tb_free(TranslationBlock *tb) { + tcg_lock(); /* In practice this is mostly used for single use temporary TB Ignore the hard cases and just back up if this TB happens to be the last one generated. */ @@ -786,6 +790,7 @@ void tb_free(TranslationBlock *tb) tcg_ctx.code_gen_ptr = tb->tc_ptr; tcg_ctx.tb_ctx.nb_tbs--; } + tcg_unlock(); } static inline void invalidate_page_bitmap(PageDesc *p) @@ -841,6 +846,7 @@ void tb_flush(CPUState *cpu) ((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer)) / tcg_ctx.tb_ctx.nb_tbs : 0); #endif + tcg_lock(); if ((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) > tcg_ctx.code_gen_buffer_size) { cpu_abort(cpu, "Internal error: code buffer overflow\n"); @@ -859,6 +865,7 @@ void tb_flush(CPUState *cpu) /* XXX: flush processor icache at this point if cache flush is expensive */ tcg_ctx.tb_ctx.tb_flush_count++; + tcg_unlock(); } #ifdef DEBUG_TB_CHECK @@ -1317,8 +1324,10 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, uint32_t current_flags = 0; #endif /* TARGET_HAS_PRECISE_SMC */ + tcg_lock(); p = page_find(start >> TARGET_PAGE_BITS); if (!p) { + tcg_unlock(); return; } #if defined(TARGET_HAS_PRECISE_SMC) @@ -1389,6 +1398,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, cpu_loop_exit_noexc(cpu); } #endif + tcg_unlock(); } #ifdef CONFIG_SOFTMMU @@ -1506,13 +1516,16 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) { int m_min, m_max, m; uintptr_t v; - TranslationBlock *tb; + TranslationBlock *tb, *r; + tcg_lock(); if (tcg_ctx.tb_ctx.nb_tbs <= 0) { + tcg_unlock(); return NULL; } if (tc_ptr < (uintptr_t)tcg_ctx.code_gen_buffer || tc_ptr >= (uintptr_t)tcg_ctx.code_gen_ptr) { + tcg_unlock(); return NULL; } /* binary search (cf Knuth) */ @@ -1523,6 +1536,7 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) tb = &tcg_ctx.tb_ctx.tbs[m]; v = (uintptr_t)tb->tc_ptr; if (v == tc_ptr) { + tcg_unlock(); return tb; } else if (tc_ptr < v) { m_max = m - 1; @@ -1530,7 +1544,9 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) m_min = m + 1; } } - return &tcg_ctx.tb_ctx.tbs[m_max]; + r = &tcg_ctx.tb_ctx.tbs[m_max]; + tcg_unlock(); + return r; } #if !defined(CONFIG_USER_ONLY) diff --git a/ui/console.c b/ui/console.c index c24bfe422d..44b46fd3d1 100644 --- a/ui/console.c +++ b/ui/console.c @@ -868,7 +868,7 @@ static void console_putchar(QemuConsole *s, int ch) } else { if (s->nb_esc_params < MAX_ESC_PARAMS) s->nb_esc_params++; - if (ch == ';') + if (ch == ';' || ch == '?') break; trace_console_putchar_csi(s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params); diff --git a/ui/vnc.c b/ui/vnc.c index 853b57e982..516c82b544 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -58,6 +58,8 @@ static const struct timeval VNC_REFRESH_LOSSY = { 2, 0 }; static QTAILQ_HEAD(, VncDisplay) vnc_displays = QTAILQ_HEAD_INITIALIZER(vnc_displays); +static int allowed_connections = 0; + static int vnc_cursor_define(VncState *vs); static void vnc_release_modifiers(VncState *vs); @@ -1195,6 +1197,7 @@ static void vnc_disconnect_start(VncState *vs) void vnc_disconnect_finish(VncState *vs) { int i; + static int num_disconnects = 0; vnc_jobs_join(vs); /* Wait encoding jobs */ @@ -1245,6 +1248,13 @@ void vnc_disconnect_finish(VncState *vs) object_unref(OBJECT(vs->sioc)); vs->sioc = NULL; g_free(vs); + + num_disconnects++; + if (allowed_connections > 0 && allowed_connections <= num_disconnects) { + VNC_DEBUG("Maximum number of disconnects (%d) reached:" + " Session terminating\n", allowed_connections); + exit(0); + } } ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp) @@ -3243,6 +3253,39 @@ static void vnc_display_print_local_addr(VncDisplay *vs) qapi_free_SocketAddress(addr); } +static void read_file_password(const char *id, const char *filename) +{ + FILE *pfile = NULL; + char *passwd = NULL; + int start = 0, length = 0, rc = 0; + + if (strlen(filename) == 0) { + printf("No file supplied\n"); + return; + } + + pfile = fopen(filename, "r"); + if (pfile == NULL) { + printf("Could not read from %s\n", filename); + return; + } + + start = ftell(pfile); + fseek(pfile, 0L, SEEK_END); + length = ftell(pfile); + fseek(pfile, 0L, start); + + passwd = g_malloc(length + 1); + rc = fread(passwd, 1, length, pfile); + fclose(pfile); + + if (rc == length && rc > 0) { + vnc_display_password(id, passwd); + } + + g_free(passwd); +} + static QemuOptsList qemu_vnc_opts = { .name = "vnc", .head = QTAILQ_HEAD_INITIALIZER(qemu_vnc_opts.head), @@ -3273,6 +3316,9 @@ static QemuOptsList qemu_vnc_opts = { },{ .name = "connections", .type = QEMU_OPT_NUMBER, + },{ + .name = "allowed-connections", + .type = QEMU_OPT_NUMBER, },{ .name = "to", .type = QEMU_OPT_NUMBER, @@ -3285,6 +3331,9 @@ static QemuOptsList qemu_vnc_opts = { },{ .name = "password", .type = QEMU_OPT_BOOL, + },{ + .name = "password-file", + .type = QEMU_OPT_STRING, },{ .name = "reverse", .type = QEMU_OPT_BOOL, @@ -3522,6 +3571,7 @@ void vnc_display_open(const char *id, Error **errp) const char *share, *device_id; QemuConsole *con; bool password = false; + const char *password_file; bool reverse = false; const char *vnc; char *h; @@ -3650,6 +3700,10 @@ void vnc_display_open(const char *id, Error **errp) goto fail; } } + password_file = qemu_opt_get(opts, "password-file"); + if (password_file) { + read_file_password(id, password_file); + } reverse = qemu_opt_get_bool(opts, "reverse", false); lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true); @@ -3739,6 +3793,7 @@ void vnc_display_open(const char *id, Error **errp) vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE; } vs->connections_limit = qemu_opt_get_number(opts, "connections", 32); + allowed_connections = qemu_opt_get_number(opts, "allowed-connections", 0); #ifdef CONFIG_VNC_JPEG vs->lossy = qemu_opt_get_bool(opts, "lossy", false); diff --git a/user-exec.c b/user-exec.c index 95f9f97c5c..eaeb0b4aad 100644 --- a/user-exec.c +++ b/user-exec.c @@ -65,6 +65,10 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif + + /* Maybe we're still holding the TB fiddling lock? */ + tb_lock_reset(); + /* XXX: locking issue */ if (is_write && h2g_valid(address)) { switch (page_unprotect(h2g(address), pc)) { diff --git a/vl.c b/vl.c index c4eeaffb91..ec310986d5 100644 --- a/vl.c +++ b/vl.c @@ -160,6 +160,7 @@ int smp_threads = 1; int acpi_enabled = 1; int no_hpet = 0; int fd_bootchk = 1; +int slirp_nooutgoing = 0; static int no_reboot; int no_shutdown = 0; int cursor_hide = 1; @@ -3362,6 +3363,14 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_singlestep: singlestep = 1; break; + case QEMU_OPTION_nooutgoing: + slirp_nooutgoing = inet_addr(optarg); + if (slirp_nooutgoing == INADDR_NONE) { + printf("Invalid address: %s.\nOnly addresses of the format " + "xxx.xxx.xxx.xxx are supported.\n", optarg); + exit(1); + } + break; case QEMU_OPTION_S: autostart = 0; break;