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 wait_event_interruptible_timeout(midi_sleeper[dev], 90 !midi_devs[dev]->buffer_status(dev), HZ/10); 91} 92 93static void midi_input_intr(int dev, unsigned char data) 94{ 95 if (midi_in_buf[dev] == NULL) 96 return; 97 98 if (data == 0xfe) /* 99 * Active sensing 100 */ 101 return; /* 102 * Ignore 103 */ 104 105 if (SPACE_AVAIL(midi_in_buf[dev])) { 106 QUEUE_BYTE(midi_in_buf[dev], data); 107 wake_up(&input_sleeper[dev]); 108 } 109} 110 111static void midi_output_intr(int dev) 112{ 113 /* 114 * Currently NOP 115 */ 116} 117 118static void midi_poll(unsigned long dummy) 119{ 120 unsigned long flags; 121 int dev; 122 123 spin_lock_irqsave(&lock, flags); 124 if (open_devs) 125 { 126 for (dev = 0; dev < num_midis; dev++) 127 if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL) 128 { 129 while (DATA_AVAIL(midi_out_buf[dev])) 130 { 131 int ok; 132 int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head]; 133 134 spin_unlock_irqrestore(&lock,flags);/* Give some time to others */ 135 ok = midi_devs[dev]->outputc(dev, c); 136 spin_lock_irqsave(&lock, flags); 137 if (!ok) 138 break; 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] = 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] = 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 wait_event_interruptible(midi_sleeper[dev], 236 !DATA_AVAIL(midi_out_buf[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 if (wait_event_interruptible(midi_sleeper[dev], 285 SPACE_AVAIL(midi_out_buf[dev]))) 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 - CAN'T 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 wait_event_interruptible_timeout(input_sleeper[dev], 328 DATA_AVAIL(midi_in_buf[dev]), 329 parms[dev].prech_timeout); 330 331 if (signal_pending(current)) 332 c = -EINTR; /* The user is getting restless */ 333 } 334 if (c == 0 && DATA_AVAIL(midi_in_buf[dev])) /* 335 * Got some bytes 336 */ 337 { 338 n = DATA_AVAIL(midi_in_buf[dev]); 339 if (n > count) 340 n = count; 341 c = 0; 342 343 while (c < n) 344 { 345 char *fixit; 346 REMOVE_BYTE(midi_in_buf[dev], tmp_data); 347 fixit = (char *) &tmp_data; 348 /* BROKE BROKE BROKE */ 349 /* yes removed the cli() brackets again 350 should q->len,tail&head be atomic_t? */ 351 if (copy_to_user(&(buf)[c], fixit, 1)) { 352 c = -EFAULT; 353 goto out; 354 } 355 c++; 356 } 357 } 358out: 359 return c; 360} 361 362int MIDIbuf_ioctl(int dev, struct file *file, 363 unsigned int cmd, void __user *arg) 364{ 365 int val; 366 367 dev = dev >> 4; 368 369 if (((cmd >> 8) & 0xff) == 'C') 370 { 371 if (midi_devs[dev]->coproc) /* Coprocessor ioctl */ 372 return midi_devs[dev]->coproc->ioctl(midi_devs[dev]->coproc->devc, cmd, arg, 0); 373/* printk("/dev/midi%d: No coprocessor for this device\n", dev);*/ 374 return -ENXIO; 375 } 376 else 377 { 378 switch (cmd) 379 { 380 case SNDCTL_MIDI_PRETIME: 381 if (get_user(val, (int __user *)arg)) 382 return -EFAULT; 383 if (val < 0) 384 val = 0; 385 val = (HZ * val) / 10; 386 parms[dev].prech_timeout = val; 387 return put_user(val, (int __user *)arg); 388 389 default: 390 if (!midi_devs[dev]->ioctl) 391 return -EINVAL; 392 return midi_devs[dev]->ioctl(dev, cmd, arg); 393 } 394 } 395} 396 397/* No kernel lock - fine */ 398unsigned int MIDIbuf_poll(int dev, struct file *file, poll_table * wait) 399{ 400 unsigned int mask = 0; 401 402 dev = dev >> 4; 403 404 /* input */ 405 poll_wait(file, &input_sleeper[dev], wait); 406 if (DATA_AVAIL(midi_in_buf[dev])) 407 mask |= POLLIN | POLLRDNORM; 408 409 /* output */ 410 poll_wait(file, &midi_sleeper[dev], wait); 411 if (!SPACE_AVAIL(midi_out_buf[dev])) 412 mask |= POLLOUT | POLLWRNORM; 413 414 return mask; 415} 416 417 418int MIDIbuf_avail(int dev) 419{ 420 if (midi_in_buf[dev]) 421 return DATA_AVAIL (midi_in_buf[dev]); 422 return 0; 423} 424EXPORT_SYMBOL(MIDIbuf_avail); 425 426