1/* 2 * sound/oss/midibuf.c 3 * 4 * Device file manager for /dev/midi# 5 */ 6/* 7 * Copyright (C) by Hannu Savolainen 1993-1997 8 * 9 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) 10 * Version 2 (June 1991). See the "COPYING" file distributed with this software 11 * for more info. 12 */ 13/* 14 * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) 15 */ 16#include <linux/stddef.h> 17#include <linux/kmod.h> 18#include <linux/spinlock.h> 19#define MIDIBUF_C 20 21#include "sound_config.h" 22 23 24/* 25 * Don't make MAX_QUEUE_SIZE larger than 4000 26 */ 27 28#define MAX_QUEUE_SIZE 4000 29 30static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV]; 31static wait_queue_head_t input_sleeper[MAX_MIDI_DEV]; 32 33struct midi_buf 34{ 35 int len, head, tail; 36 unsigned char queue[MAX_QUEUE_SIZE]; 37}; 38 39struct midi_parms 40{ 41 long prech_timeout; /* 42 * Timeout before the first ch 43 */ 44}; 45 46static struct midi_buf *midi_out_buf[MAX_MIDI_DEV] = {NULL}; 47static struct midi_buf *midi_in_buf[MAX_MIDI_DEV] = {NULL}; 48static struct midi_parms parms[MAX_MIDI_DEV]; 49 50static void midi_poll(unsigned long dummy); 51 52 53static DEFINE_TIMER(poll_timer, midi_poll, 0, 0); 54 55static volatile int open_devs; 56static DEFINE_SPINLOCK(lock); 57 58#define DATA_AVAIL(q) (q->len) 59#define SPACE_AVAIL(q) (MAX_QUEUE_SIZE - q->len) 60 61#define QUEUE_BYTE(q, data) \ 62 if (SPACE_AVAIL(q)) \ 63 { \ 64 unsigned long flags; \ 65 spin_lock_irqsave(&lock, flags); \ 66 q->queue[q->tail] = (data); \ 67 q->len++; q->tail = (q->tail+1) % MAX_QUEUE_SIZE; \ 68 spin_unlock_irqrestore(&lock, flags); \ 69 } 70 71#define REMOVE_BYTE(q, data) \ 72 if (DATA_AVAIL(q)) \ 73 { \ 74 unsigned long flags; \ 75 spin_lock_irqsave(&lock, flags); \ 76 data = q->queue[q->head]; \ 77 q->len--; q->head = (q->head+1) % MAX_QUEUE_SIZE; \ 78 spin_unlock_irqrestore(&lock, flags); \ 79 } 80 81static void drain_midi_queue(int dev) 82{ 83 84 /* 85 * Give the Midi driver time to drain its output queues 86 */ 87 88 if (midi_devs[dev]->buffer_status != NULL) 89 while (!signal_pending(current) && midi_devs[dev]->buffer_status(dev)) 90 interruptible_sleep_on_timeout(&midi_sleeper[dev], 91 HZ/10); 92} 93 94static void midi_input_intr(int dev, unsigned char data) 95{ 96 if (midi_in_buf[dev] == NULL) 97 return; 98 99 if (data == 0xfe) /* 100 * Active sensing 101 */ 102 return; /* 103 * Ignore 104 */ 105 106 if (SPACE_AVAIL(midi_in_buf[dev])) { 107 QUEUE_BYTE(midi_in_buf[dev], data); 108 wake_up(&input_sleeper[dev]); 109 } 110} 111 112static void midi_output_intr(int dev) 113{ 114 /* 115 * Currently NOP 116 */ 117} 118 119static void midi_poll(unsigned long dummy) 120{ 121 unsigned long flags; 122 int dev; 123 124 spin_lock_irqsave(&lock, flags); 125 if (open_devs) 126 { 127 for (dev = 0; dev < num_midis; dev++) 128 if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL) 129 { 130 int ok = 1; 131 132 while (DATA_AVAIL(midi_out_buf[dev]) && ok) 133 { 134 int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head]; 135 136 spin_unlock_irqrestore(&lock,flags);/* Give some time to others */ 137 ok = midi_devs[dev]->outputc(dev, c); 138 spin_lock_irqsave(&lock, flags); 139 midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE; 140 midi_out_buf[dev]->len--; 141 } 142 143 if (DATA_AVAIL(midi_out_buf[dev]) < 100) 144 wake_up(&midi_sleeper[dev]); 145 } 146 poll_timer.expires = (1) + jiffies; 147 add_timer(&poll_timer); 148 /* 149 * Come back later 150 */ 151 } 152 spin_unlock_irqrestore(&lock, flags); 153} 154 155int MIDIbuf_open(int dev, struct file *file) 156{ 157 int mode, err; 158 159 dev = dev >> 4; 160 mode = translate_mode(file); 161 162 if (num_midis > MAX_MIDI_DEV) 163 { 164 printk(KERN_ERR "midi: Too many midi interfaces\n"); 165 num_midis = MAX_MIDI_DEV; 166 } 167 if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) 168 return -ENXIO; 169 /* 170 * Interrupts disabled. Be careful 171 */ 172 173 module_put(midi_devs[dev]->owner); 174 175 if ((err = midi_devs[dev]->open(dev, mode, 176 midi_input_intr, midi_output_intr)) < 0) 177 return err; 178 179 parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT; 180 midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf)); 181 182 if (midi_in_buf[dev] == NULL) 183 { 184 printk(KERN_WARNING "midi: Can't allocate buffer\n"); 185 midi_devs[dev]->close(dev); 186 return -EIO; 187 } 188 midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; 189 190 midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf)); 191 192 if (midi_out_buf[dev] == NULL) 193 { 194 printk(KERN_WARNING "midi: Can't allocate buffer\n"); 195 midi_devs[dev]->close(dev); 196 vfree(midi_in_buf[dev]); 197 midi_in_buf[dev] = NULL; 198 return -EIO; 199 } 200 midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; 201 open_devs++; 202 203 init_waitqueue_head(&midi_sleeper[dev]); 204 init_waitqueue_head(&input_sleeper[dev]); 205 206 if (open_devs < 2) /* This was first open */ 207 { 208 poll_timer.expires = 1 + jiffies; 209 add_timer(&poll_timer); /* Start polling */ 210 } 211 return err; 212} 213 214void MIDIbuf_release(int dev, struct file *file) 215{ 216 int mode; 217 218 dev = dev >> 4; 219 mode = translate_mode(file); 220 221 if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) 222 return; 223 224 /* 225 * Wait until the queue is empty 226 */ 227 228 if (mode != OPEN_READ) 229 { 230 midi_devs[dev]->outputc(dev, 0xfe); /* 231 * Active sensing to shut the 232 * devices 233 */ 234 235 while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev])) 236 interruptible_sleep_on(&midi_sleeper[dev]); 237 /* 238 * Sync 239 */ 240 241 drain_midi_queue(dev); /* 242 * Ensure the output queues are empty 243 */ 244 } 245 246 midi_devs[dev]->close(dev); 247 248 open_devs--; 249 if (open_devs == 0) 250 del_timer_sync(&poll_timer); 251 vfree(midi_in_buf[dev]); 252 vfree(midi_out_buf[dev]); 253 midi_in_buf[dev] = NULL; 254 midi_out_buf[dev] = NULL; 255 256 module_put(midi_devs[dev]->owner); 257} 258 259int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count) 260{ 261 int c, n, i; 262 unsigned char tmp_data; 263 264 dev = dev >> 4; 265 266 if (!count) 267 return 0; 268 269 c = 0; 270 271 while (c < count) 272 { 273 n = SPACE_AVAIL(midi_out_buf[dev]); 274 275 if (n == 0) { /* 276 * No space just now. 277 */ 278 279 if (file->f_flags & O_NONBLOCK) { 280 c = -EAGAIN; 281 goto out; 282 } 283 284 interruptible_sleep_on(&midi_sleeper[dev]); 285 if (signal_pending(current)) 286 { 287 c = -EINTR; 288 goto out; 289 } 290 n = SPACE_AVAIL(midi_out_buf[dev]); 291 } 292 if (n > (count - c)) 293 n = count - c; 294 295 for (i = 0; i < n; i++) 296 { 297 /* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */ 298 /* yes, think the same, so I removed the cli() brackets 299 QUEUE_BYTE is protected against interrupts */ 300 if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) { 301 c = -EFAULT; 302 goto out; 303 } 304 QUEUE_BYTE(midi_out_buf[dev], tmp_data); 305 c++; 306 } 307 } 308out: 309 return c; 310} 311 312 313int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count) 314{ 315 int n, c = 0; 316 unsigned char tmp_data; 317 318 dev = dev >> 4; 319 320 if (!DATA_AVAIL(midi_in_buf[dev])) { /* 321 * No data yet, wait 322 */ 323 if (file->f_flags & O_NONBLOCK) { 324 c = -EAGAIN; 325 goto out; 326 } 327 interruptible_sleep_on_timeout(&input_sleeper[dev], 328 parms[dev].prech_timeout); 329 330 if (signal_pending(current)) 331 c = -EINTR; /* The user is getting restless */ 332 } 333 if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) /* 334 * Got some bytes 335 */ 336 { 337 n = DATA_AVAIL(midi_in_buf[dev]); 338 if (n > count) 339 n = count; 340 c = 0; 341 342 while (c < n) 343 { 344 char *fixit; 345 REMOVE_BYTE(midi_in_buf[dev], tmp_data); 346 fixit = (char *) &tmp_data; 347 /* BROKE BROKE BROKE */ 348 /* yes removed the cli() brackets again 349 should q->len,tail&head be atomic_t? */ 350 if (copy_to_user(&(buf)[c], fixit, 1)) { 351 c = -EFAULT; 352 goto out; 353 } 354 c++; 355 } 356 } 357out: 358 return c; 359} 360 361int MIDIbuf_ioctl(int dev, struct file *file, 362 unsigned int cmd, void __user *arg) 363{ 364 int val; 365 366 dev = dev >> 4; 367 368 if (((cmd >> 8) & 0xff) == 'C') 369 { 370 if (midi_devs[dev]->coproc) /* Coprocessor ioctl */ 371 return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0); 372/* printk("/dev/midi%d: No coprocessor for this device\n", dev);*/ 373 return -ENXIO; 374 } 375 else 376 { 377 switch (cmd) 378 { 379 case SNDCTL_MIDI_PRETIME: 380 if (get_user(val, (int __user *)arg)) 381 return -EFAULT; 382 if (val < 0) 383 val = 0; 384 val = (HZ * val) / 10; 385 parms[dev].prech_timeout = val; 386 return put_user(val, (int __user *)arg); 387 388 default: 389 if (!midi_devs[dev]->ioctl) 390 return -EINVAL; 391 return midi_devs[dev]->ioctl(dev, cmd, arg); 392 } 393 } 394} 395 396/* No kernel lock - fine */ 397unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait) 398{ 399 unsigned int mask = 0; 400 401 dev = dev >> 4; 402 403 /* input */ 404 poll_wait(file, &input_sleeper[dev], wait); 405 if (DATA_AVAIL(midi_in_buf[dev])) 406 mask |= POLLIN | POLLRDNORM; 407 408 /* output */ 409 poll_wait(file, &midi_sleeper[dev], wait); 410 if (!SPACE_AVAIL(midi_out_buf[dev])) 411 mask |= POLLOUT | POLLWRNORM; 412 413 return mask; 414} 415 416 417int MIDIbuf_avail(int dev) 418{ 419 if (midi_in_buf[dev]) 420 return DATA_AVAIL (midi_in_buf[dev]); 421 return 0; 422} 423EXPORT_SYMBOL(MIDIbuf_avail); 424