int
snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev)
{
	struct seq_oss_midi *mdev;
	struct snd_seq_port_subscribe subs;

	if ((mdev = get_mididev(dp, dev)) == NULL)
		return -ENODEV;
	if (! mdev->opened || mdev->devinfo != dp) {
		snd_use_lock_free(&mdev->use_lock);
		return 0;
	}

	debug_printk(("closing client %d port %d mode %d\n", mdev->client, mdev->port, mdev->opened));
	memset(&subs, 0, sizeof(subs));
	if (mdev->opened & PERM_WRITE) {
		subs.sender = dp->addr;
		subs.dest.client = mdev->client;
		subs.dest.port = mdev->port;
		snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
	}
	if (mdev->opened & PERM_READ) {
		subs.sender.client = mdev->client;
		subs.sender.port = mdev->port;
		subs.dest = dp->addr;
		snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs);
	}

	mdev->opened = 0;
	mdev->devinfo = NULL;

	snd_use_lock_free(&mdev->use_lock);
	return 0;
}
Exemple #2
0
/********************************************************************
 * t1_getreg_isr()
 *
 * Called in interrupt context to retrieve a value already requested
 * by the normal t1_getreg().
 *******************************************************************/
static inline int t1_getreg_isr(struct t1 *wc, int addr)
{
	int hit=-1;
	int ret;
	unsigned int x;
	
	/* find our requested command */
	for (x = 0;x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) {
		if ((wc->cmdq.cmds[x].flags & __CMD_RD) &&
		    (wc->cmdq.cmds[x].address==addr)) 
		{
			if (wc->cmdq.cmds[x].flags & __CMD_FIN) {
				hit = x;
				break;
			}
			else {
				/* still in progress. */
				return -1;
			}
		}
	}

	if (hit < 0) {
		debug_printk(2, "t1_getreg_isr() no addr=%02x\n", addr);
		return -1; /* oops, couldn't find it */
	}

	ret = wc->cmdq.cmds[hit].data;
	memset(&wc->cmdq.cmds[hit], 0, sizeof(struct command));

	return ret;
}
Exemple #3
0
static int __init
register_device(void)
{
    int rc;

    mutex_lock(&register_mutex);
    if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
                      NULL, 0,
                      &seq_oss_f_ops, NULL,
                      SNDRV_SEQ_OSS_DEVNAME)) < 0) {
        snd_printk(KERN_ERR "can't register device seq\n");
        mutex_unlock(&register_mutex);
        return rc;
    }
    if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
                      NULL, 0,
                      &seq_oss_f_ops, NULL,
                      SNDRV_SEQ_OSS_DEVNAME)) < 0) {
        snd_printk(KERN_ERR "can't register device music\n");
        snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
        mutex_unlock(&register_mutex);
        return rc;
    }
    debug_printk(("device registered\n"));
    mutex_unlock(&register_mutex);
    return 0;
}
Exemple #4
0
static void free_mem(void *mem, struct memory_block *heap, void *base)
{
	struct alloc_header *header = (struct alloc_header *)((unsigned int *)mem - sizeof(struct alloc_header));
	unsigned int chunks = header->chunks;
	unsigned int index_block = addr_to_block((void *)header, base);
	unsigned int block_to_free;
	int i;

	if (header->magic != MAGIC)
		debug_printk("Corrupted or invalid object to be free !\n");

	if (chunks < CHUNK_PER_BLOCK) {
		heap[index_block].free_mask &= ~(MASK(chunks) << addr_to_chunks_offset((void *)header, base));
		heap[index_block].free_chunks += chunks;
	} else {
		block_to_free = chunks / CHUNK_PER_BLOCK;
		chunks = chunks % CHUNK_PER_BLOCK;

		for (i = 0; i < block_to_free; i++) {
			heap[index_block + i].free_mask = 0;
			heap[index_block + i].free_chunks = CHUNK_PER_BLOCK;
		}

		heap[index_block + block_to_free].free_mask &= ~MASK(chunks);
		heap[index_block + block_to_free].free_chunks += chunks;
	}
}
void
snd_seq_oss_synth_setup(struct seq_oss_devinfo *dp)
{
	int i;
	struct seq_oss_synth *rec;
	struct seq_oss_synthinfo *info;

	dp->max_synthdev = max_synth_devs;
	dp->synth_opened = 0;
	memset(dp->synths, 0, sizeof(dp->synths));
	for (i = 0; i < dp->max_synthdev; i++) {
		rec = get_sdev(i);
		if (rec == NULL)
			continue;
		if (rec->oper.open == NULL || rec->oper.close == NULL) {
			snd_use_lock_free(&rec->use_lock);
			continue;
		}
		info = &dp->synths[i];
		info->arg.app_index = dp->port;
		info->arg.file_mode = dp->file_mode;
		info->arg.seq_mode = dp->seq_mode;
		if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH)
			info->arg.event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
		else
			info->arg.event_passing = SNDRV_SEQ_OSS_PASS_EVENTS;
		info->opened = 0;
		if (!try_module_get(rec->oper.owner)) {
			snd_use_lock_free(&rec->use_lock);
			continue;
		}
		if (rec->oper.open(&info->arg, rec->private_data) < 0) {
			module_put(rec->oper.owner);
			snd_use_lock_free(&rec->use_lock);
			continue;
		}
		info->nr_voices = rec->nr_voices;
		if (info->nr_voices > 0) {
			info->ch = kcalloc(info->nr_voices, sizeof(struct seq_oss_chinfo), GFP_KERNEL);
			if (!info->ch) {
				snd_printk(KERN_ERR "Cannot malloc\n");
				rec->oper.close(&info->arg);
				module_put(rec->oper.owner);
				snd_use_lock_free(&rec->use_lock);
				continue;
			}
			reset_channels(info);
		}
#ifdef CONFIG_DEBUG_PRINTK
		debug_printk(("synth %d assigned\n", i));
#else
		debug_;
#endif
		info->opened++;
		rec->opened++;
		dp->synth_opened++;
		snd_use_lock_free(&rec->use_lock);
	}
}
Exemple #6
0
/*
 * create sequencer client for OSS sequencer
 */
int __init
snd_seq_oss_create_client(void)
{
	int rc;
	struct snd_seq_port_info *port;
	struct snd_seq_port_callback port_callback;

	port = kmalloc(sizeof(*port), GFP_KERNEL);
	if (!port) {
		rc = -ENOMEM;
		goto __error;
	}

	/* create ALSA client */
	rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS,
					  "OSS sequencer");
	if (rc < 0)
		goto __error;

	system_client = rc;
	debug_printk(("new client = %d\n", rc));

	/* look up midi devices */
	snd_seq_oss_midi_lookup_ports(system_client);

	/* create annoucement receiver port */
	memset(port, 0, sizeof(*port));
	strcpy(port->name, "Receiver");
	port->addr.client = system_client;
	port->capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
	port->type = 0;

	memset(&port_callback, 0, sizeof(port_callback));
	/* don't set port_callback.owner here. otherwise the module counter
	 * is incremented and we can no longer release the module..
	 */
	port_callback.event_input = receive_announce;
	port->kernel = &port_callback;
	
	call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, port);
	if ((system_port = port->addr.port) >= 0) {
		struct snd_seq_port_subscribe subs;

		memset(&subs, 0, sizeof(subs));
		subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
		subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
		subs.dest.client = system_client;
		subs.dest.port = system_port;
		call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
	}
	rc = 0;

 __error:
	kfree(port);
	return rc;
}
static void
unregister_device(void)
{
    mutex_lock(&register_mutex);
    debug_printk(("device unregistered\n"));
    if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, NULL, 0) < 0)
        snd_printk(KERN_ERR "error unregister device music\n");
    if (snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0) < 0)
        snd_printk(KERN_ERR "error unregister device seq\n");
    mutex_unlock(&register_mutex);
}
/*
 * registration of the synth device
 */
int
snd_seq_oss_synth_register(struct snd_seq_device *dev)
{
	int i;
	struct seq_oss_synth *rec;
	struct snd_seq_oss_reg *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
	unsigned long flags;

	if ((rec = kzalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
		snd_printk(KERN_ERR "can't malloc synth info\n");
		return -ENOMEM;
	}
	rec->seq_device = -1;
	rec->synth_type = reg->type;
	rec->synth_subtype = reg->subtype;
	rec->nr_voices = reg->nvoices;
	rec->oper = reg->oper;
	rec->private_data = reg->private_data;
	rec->opened = 0;
	snd_use_lock_init(&rec->use_lock);

	/* copy and truncate the name of synth device */
	strlcpy(rec->name, dev->name, sizeof(rec->name));

	/* registration */
	spin_lock_irqsave(&register_lock, flags);
	for (i = 0; i < max_synth_devs; i++) {
		if (synth_devs[i] == NULL)
			break;
	}
	if (i >= max_synth_devs) {
		if (max_synth_devs >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS) {
			spin_unlock_irqrestore(&register_lock, flags);
			snd_printk(KERN_ERR "no more synth slot\n");
			kfree(rec);
			return -ENOMEM;
		}
		max_synth_devs++;
	}
	rec->seq_device = i;
	synth_devs[i] = rec;
#ifdef CONFIG_DEBUG_PRINTK
	debug_printk(("synth %s registered %d\n", rec->name, i));
#else
	debug_;
#endif
	spin_unlock_irqrestore(&register_lock, flags);
	dev->driver_data = rec;
#ifdef SNDRV_OSS_INFO_DEV_SYNTH
	if (i < SNDRV_CARDS)
		snd_oss_info_register(SNDRV_OSS_INFO_DEV_SYNTH, i, rec->name);
#endif
	return 0;
}
Exemple #9
0
/***************************************************************************
 * clean_leftovers()
 *
 * Check for unconsumed isr register reads and clean them up.
 **************************************************************************/
static inline void clean_leftovers(struct t1 *wc)
{
	unsigned int x;
	int count = 0;
	
	/* find our requested command */
	for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) {
		if ((wc->cmdq.cmds[x].flags & __CMD_RD) &&
		    (wc->cmdq.cmds[x].flags & __CMD_ISR) &&
		    !(wc->cmdq.cmds[x].flags & __CMD_FIN)) {
			debug_printk(1,"leftover isr read! %d", count);
			memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x]));
		}
	}
}
Exemple #10
0
static int t1xxp_startup(struct zt_span *span)
{
	struct t1 *wc = span->pvt;
	int i;

	/* initialize the start value for the entire chunk of last ec buffer */
	for (i = 0; i < span->channels; i++) {
		memset(wc->ec_chunk1[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE);
		memset(wc->ec_chunk2[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE);
	}

	/* Reset framer with proper parameters and start */
	t1xxp_framer_start(wc, span);
	debug_printk(1, "Calling startup (flags is %d)\n", span->flags);

	return 0;
}
/*
 * reset the midi device and close it:
 * so far, only close the device.
 */
void
snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
{
	struct seq_oss_midi *mdev;

	if ((mdev = get_mididev(dp, dev)) == NULL)
		return;
	if (! mdev->opened) {
		snd_use_lock_free(&mdev->use_lock);
		return;
	}

	if (mdev->opened & PERM_WRITE) {
		struct snd_seq_event ev;
		int c;

		debug_printk(("resetting client %d port %d\n", mdev->client, mdev->port));
		memset(&ev, 0, sizeof(ev));
		ev.dest.client = mdev->client;
		ev.dest.port = mdev->port;
		ev.queue = dp->queue;
		ev.source.port = dp->port;
		if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
			ev.type = SNDRV_SEQ_EVENT_SENSING;
			snd_seq_oss_dispatch(dp, &ev, 0, 0);
		}
		for (c = 0; c < 16; c++) {
			ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
			ev.data.control.channel = c;
			ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
			snd_seq_oss_dispatch(dp, &ev, 0, 0);
			if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
				ev.data.control.param =
					MIDI_CTL_RESET_CONTROLLERS;
				snd_seq_oss_dispatch(dp, &ev, 0, 0);
				ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
				ev.data.control.value = 0;
				snd_seq_oss_dispatch(dp, &ev, 0, 0);
			}
		}
	}
	// snd_seq_oss_midi_close(dp, dev);
	snd_use_lock_free(&mdev->use_lock);
}
void
snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
{
	int i;
	struct seq_oss_synth *rec;
	struct seq_oss_synthinfo *info;

	if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
		return;
	for (i = 0; i < dp->max_synthdev; i++) {
		info = &dp->synths[i];
		if (! info->opened)
			continue;
		if (info->is_midi) {
			if (midi_synth_dev.opened > 0) {
				snd_seq_oss_midi_close(dp, info->midi_mapped);
				midi_synth_dev.opened--;
			}
		} else {
			rec = get_sdev(i);
			if (rec == NULL)
				continue;
			if (rec->opened > 0) {
#ifdef CONFIG_DEBUG_PRINTK
				debug_printk(("synth %d closed\n", i));
#else
				debug_;
#endif
				rec->oper.close(&info->arg);
				module_put(rec->oper.owner);
				rec->opened = 0;
			}
			snd_use_lock_free(&rec->use_lock);
		}
		kfree(info->sysex);
		info->sysex = NULL;
		kfree(info->ch);
		info->ch = NULL;
	}
	dp->synth_opened = 0;
	dp->max_synthdev = 0;
}
Exemple #13
0
void svc_sem_wait(struct semaphore *sem)
{
	struct thread *current_thread;

	thread_lock(state);

	if (--sem->count < 0) {
		debug_printk("unable to got sem (%p)(%d)\r\n", sem, sem->count);

		current_thread = get_current_thread();
		current_thread->state = THREAD_BLOCKED;

		insert_waiting_thread(sem, current_thread);
		sem->waiting++;

		arch_system_call(SVC_THREAD_SWITCH, NULL, NULL, NULL);
	}

	thread_unlock(state);
}
Exemple #14
0
void
snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
{
	int i;
	seq_oss_synth_t *rec;
	seq_oss_synthinfo_t *info;

	snd_assert(dp->max_synthdev <= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS, return);
	for (i = 0; i < dp->max_synthdev; i++) {
		info = &dp->synths[i];
		if (! info->opened)
			continue;
		if (info->is_midi) {
			if (midi_synth_dev.opened > 0) {
				snd_seq_oss_midi_close(dp, info->midi_mapped);
				midi_synth_dev.opened--;
			}
		} else {
			rec = get_sdev(i);
			if (rec == NULL)
				continue;
			if (rec->opened > 0) {
				debug_printk(("synth %d closed\n", i));
				rec->oper.close(&info->arg);
				module_put(rec->oper.owner);
				rec->opened = 0;
			}
			snd_use_lock_free(&rec->use_lock);
		}
		if (info->sysex) {
			kfree(info->sysex);
			info->sysex = NULL;
		}
		if (info->ch) {
			kfree(info->ch);
			info->ch = NULL;
		}
	}
	dp->synth_opened = 0;
	dp->max_synthdev = 0;
}
Exemple #15
0
int main(void)
{
#ifdef CONFIG_INITCALL
	int ret;
	initcall_t *initcall;

	for (initcall = __rnk_initcalls_start; initcall < __rnk_initcalls_end; initcall++) {
		debug_printk("initcall-> %pS\n", *initcall);
		ret = (*initcall)();
		if (ret < 0)
			error_printk("initcall %pS failed: %d\n", *initcall, ret);
	}
#endif /* CONFIG_INITCALL */

	printk("Welcome to rnk\r\n");

	printk("- Initialise scheduler...\r\n");

#ifndef CONFIG_INITCALL
	schedule_init();
	time_init();
#endif /* CONFIG_INITCALL */

#ifdef CONFIG_UNWIND
	unwind_init();
#endif /* CONFIG_UNWIND */

	printk("- Add thread to scheduler\r\n");

	add_thread(&loading_thread, 1);

	printk("- Start scheduling...\r\n");
	start_schedule();

	while(1)
		;

	return 0; //Never reach
}
Exemple #16
0
static int t1xxp_rbsbits(struct zt_chan *chan, int bits)
{
	u_char m,c;
	int n,b;
	struct t1 *wc = chan->pvt;
	unsigned long flags;
	
	debug_printk(2, "Setting bits to %d on channel %s\n", bits, chan->name);
	if (wc->spantype == TYPE_E1) { /* do it E1 way */
		if (chan->chanpos == 16)
			return 0;

		n = chan->chanpos - 1;
		if (chan->chanpos > 15) n--;
		b = (n % 15);
		spin_lock_irqsave(&wc->reglock, flags);	
		c = wc->txsigs[b];
		m = (n / 15) << 2; /* nibble selector */
		c &= (0xf << m); /* keep the other nibble */
		c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
		wc->txsigs[b] = c;
		spin_unlock_irqrestore(&wc->reglock, flags);
		  /* output them to the chip */
		t1_setreg_full(wc,0x71 + b,c,1,NOT_VPM); 
	} else if (wc->span.lineconfig & ZT_CONFIG_D4) {
		n = chan->chanpos - 1;
		b = (n / 4);
		spin_lock_irqsave(&wc->reglock, flags);	
		c = wc->txsigs[b];
		m = ((3 - (n % 4)) << 1); /* nibble selector */
		c &= ~(0x3 << m); /* keep the other nibble */
		c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */
		wc->txsigs[b] = c;
		spin_unlock_irqrestore(&wc->reglock, flags);
		/* output them to the chip */
		t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); 
		t1_setreg_full(wc,0x70 + b + 6,c,1,NOT_VPM); 
	} else if (wc->span.lineconfig & ZT_CONFIG_ESF) {
Exemple #17
0
int
snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
{
	int dev, val;
	void __user *arg = (void __user *)carg;
	int __user *p = arg;

	switch (cmd) {
	case SNDCTL_TMR_TIMEBASE:
	case SNDCTL_TMR_TEMPO:
	case SNDCTL_TMR_START:
	case SNDCTL_TMR_STOP:
	case SNDCTL_TMR_CONTINUE:
	case SNDCTL_TMR_METRONOME:
	case SNDCTL_TMR_SOURCE:
	case SNDCTL_TMR_SELECT:
	case SNDCTL_SEQ_CTRLRATE:
		return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);

	case SNDCTL_SEQ_PANIC:
		debug_printk(("panic\n"));
		snd_seq_oss_reset(dp);
		return -EINVAL;

	case SNDCTL_SEQ_SYNC:
		debug_printk(("sync\n"));
		if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
			return 0;
		while (snd_seq_oss_writeq_sync(dp->writeq))
			;
		if (signal_pending(current))
			return -ERESTARTSYS;
		return 0;

	case SNDCTL_SEQ_RESET:
		debug_printk(("reset\n"));
		snd_seq_oss_reset(dp);
		return 0;

	case SNDCTL_SEQ_TESTMIDI:
		debug_printk(("test midi\n"));
		if (get_user(dev, p))
			return -EFAULT;
		return snd_seq_oss_midi_open(dp, dev, dp->file_mode);

	case SNDCTL_SEQ_GETINCOUNT:
		debug_printk(("get in count\n"));
		if (dp->readq == NULL || ! is_read_mode(dp->file_mode))
			return 0;
		return put_user(dp->readq->qlen, p) ? -EFAULT : 0;

	case SNDCTL_SEQ_GETOUTCOUNT:
		debug_printk(("get out count\n"));
		if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
			return 0;
		return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;

	case SNDCTL_SEQ_GETTIME:
		debug_printk(("get time\n"));
		return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;

	case SNDCTL_SEQ_RESETSAMPLES:
		debug_printk(("reset samples\n"));
		if (get_user(dev, p))
			return -EFAULT;
		return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);

	case SNDCTL_SEQ_NRSYNTHS:
		debug_printk(("nr synths\n"));
		return put_user(dp->max_synthdev, p) ? -EFAULT : 0;

	case SNDCTL_SEQ_NRMIDIS:
		debug_printk(("nr midis\n"));
		return put_user(dp->max_mididev, p) ? -EFAULT : 0;

	case SNDCTL_SYNTH_MEMAVL:
		debug_printk(("mem avail\n"));
		if (get_user(dev, p))
			return -EFAULT;
		val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
		return put_user(val, p) ? -EFAULT : 0;

	case SNDCTL_FM_4OP_ENABLE:
		debug_printk(("4op\n"));
		if (get_user(dev, p))
			return -EFAULT;
		snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);
		return 0;

	case SNDCTL_SYNTH_INFO:
	case SNDCTL_SYNTH_ID:
		debug_printk(("synth info\n"));
		return snd_seq_oss_synth_info_user(dp, arg);

	case SNDCTL_SEQ_OUTOFBAND:
		debug_printk(("out of band\n"));
		return snd_seq_oss_oob_user(dp, arg);

	case SNDCTL_MIDI_INFO:
		debug_printk(("midi info\n"));
		return snd_seq_oss_midi_info_user(dp, arg);

	case SNDCTL_SEQ_THRESHOLD:
		debug_printk(("threshold\n"));
		if (! is_write_mode(dp->file_mode))
			return 0;
		if (get_user(val, p))
			return -EFAULT;
		if (val < 1)
			val = 1;
		if (val >= dp->writeq->maxlen)
			val = dp->writeq->maxlen - 1;
		snd_seq_oss_writeq_set_output(dp->writeq, val);
		return 0;

	case SNDCTL_MIDI_PRETIME:
		debug_printk(("pretime\n"));
		if (dp->readq == NULL || !is_read_mode(dp->file_mode))
			return 0;
		if (get_user(val, p))
			return -EFAULT;
		if (val <= 0)
			val = -1;
		else
			val = (HZ * val) / 10;
		dp->readq->pre_event_timeout = val;
		return put_user(val, p) ? -EFAULT : 0;

	default:
		debug_printk(("others\n"));
		if (! is_write_mode(dp->file_mode))
			return -EIO;
		return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);
	}
	return 0;
}
/*
 * create sequencer client for OSS sequencer
 */
int __init
snd_seq_oss_create_client(void)
{
	int rc;
	snd_seq_client_callback_t callback;
	snd_seq_client_info_t info;
	snd_seq_port_info_t port;
	snd_seq_port_callback_t port_callback;

	/* create ALSA client */
	memset(&callback, 0, sizeof(callback));

	callback.private_data = NULL;
	callback.allow_input = 1;
	callback.allow_output = 1;

	rc = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_OSS, &callback);
	if (rc < 0)
		return rc;

	system_client = rc;
	debug_printk(("new client = %d\n", rc));

	/* set client information */
	memset(&info, 0, sizeof(info));
	info.client = system_client;
	info.type = KERNEL_CLIENT;
	strcpy(info.name, "OSS sequencer");

	rc = call_ctl(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);

	/* look up midi devices */
	snd_seq_oss_midi_lookup_ports(system_client);

	/* create annoucement receiver port */
	memset(&port, 0, sizeof(port));
	strcpy(port.name, "Receiver");
	port.addr.client = system_client;
	port.capability = SNDRV_SEQ_PORT_CAP_WRITE; /* receive only */
	port.type = 0;

	memset(&port_callback, 0, sizeof(port_callback));
	/* don't set port_callback.owner here. otherwise the module counter
	 * is incremented and we can no longer release the module..
	 */
	port_callback.event_input = receive_announce;
	port.kernel = &port_callback;
	
	call_ctl(SNDRV_SEQ_IOCTL_CREATE_PORT, &port);
	if ((system_port = port.addr.port) >= 0) {
		snd_seq_port_subscribe_t subs;

		memset(&subs, 0, sizeof(subs));
		subs.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;
		subs.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
		subs.dest.client = system_client;
		subs.dest.port = system_port;
		call_ctl(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &subs);
	}


	return 0;
}
int
snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
{
	int i;
	struct seq_oss_midi *mdev;
	unsigned long flags;

	debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port));
	/*                                    */
	if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
		return 0;
	/*                                   */
	if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
	    (pinfo->capability & PERM_READ) != PERM_READ)
		return 0;

	/*
                               
  */
	if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) {
		/*                */
		snd_use_lock_free(&mdev->use_lock);
		return 0;
	}

	/*
                             
  */
	if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
		snd_printk(KERN_ERR "can't malloc midi info\n");
		return -ENOMEM;
	}

	/*                           */
	mdev->client = pinfo->addr.client;
	mdev->port = pinfo->addr.port;
	mdev->flags = pinfo->capability;
	mdev->opened = 0;
	snd_use_lock_init(&mdev->use_lock);

	/*                                            */
	strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));

	/*                   */
	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
		snd_printk(KERN_ERR "can't malloc midi coder\n");
		kfree(mdev);
		return -ENOMEM;
	}
	/*                                                    */
	snd_midi_event_no_status(mdev->coder, 1);

	/*
                          
  */
	spin_lock_irqsave(&register_lock, flags);
	for (i = 0; i < max_midi_devs; i++) {
		if (midi_devs[i] == NULL)
			break;
	}
	if (i >= max_midi_devs) {
		if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
			spin_unlock_irqrestore(&register_lock, flags);
			snd_midi_event_free(mdev->coder);
			kfree(mdev);
			return -ENOMEM;
		}
		max_midi_devs++;
	}
	mdev->seq_device = i;
	midi_devs[mdev->seq_device] = mdev;
	spin_unlock_irqrestore(&register_lock, flags);

	return 0;
}
/*
 * register a new port if it doesn't exist yet
 */
int
snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
{
	int i;
	struct seq_oss_midi *mdev;
	unsigned long flags;

	debug_printk(("check for MIDI client %d port %d\n", pinfo->addr.client, pinfo->addr.port));
	/* the port must include generic midi */
	if (! (pinfo->type & SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC))
		return 0;
	/* either read or write subscribable */
	if ((pinfo->capability & PERM_WRITE) != PERM_WRITE &&
	    (pinfo->capability & PERM_READ) != PERM_READ)
		return 0;

	/*
	 * look for the identical slot
	 */
	if ((mdev = find_slot(pinfo->addr.client, pinfo->addr.port)) != NULL) {
		/* already exists */
		snd_use_lock_free(&mdev->use_lock);
		return 0;
	}

	/*
	 * allocate midi info record
	 */
	if ((mdev = kzalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
		snd_printk(KERN_ERR "can't malloc midi info\n");
		return -ENOMEM;
	}

	/* copy the port information */
	mdev->client = pinfo->addr.client;
	mdev->port = pinfo->addr.port;
	mdev->flags = pinfo->capability;
	mdev->opened = 0;
	snd_use_lock_init(&mdev->use_lock);

	/* copy and truncate the name of synth device */
	strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));

	/* create MIDI coder */
	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
		snd_printk(KERN_ERR "can't malloc midi coder\n");
		kfree(mdev);
		return -ENOMEM;
	}
	/* OSS sequencer adds running status to all sequences */
	snd_midi_event_no_status(mdev->coder, 1);

	/*
	 * look for en empty slot
	 */
	spin_lock_irqsave(&register_lock, flags);
	for (i = 0; i < max_midi_devs; i++) {
		if (midi_devs[i] == NULL)
			break;
	}
	if (i >= max_midi_devs) {
		if (max_midi_devs >= SNDRV_SEQ_OSS_MAX_MIDI_DEVS) {
			spin_unlock_irqrestore(&register_lock, flags);
			snd_midi_event_free(mdev->coder);
			kfree(mdev);
			return -ENOMEM;
		}
		max_midi_devs++;
	}
	mdev->seq_device = i;
	midi_devs[mdev->seq_device] = mdev;
	spin_unlock_irqrestore(&register_lock, flags);

	return 0;
}