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 while (DATA_AVAIL(midi_out_buf[dev])) 131 { 132 int ok; 133 int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head]; 134 135 spin_unlock_irqrestore(&lock,flags);/* Give some time to others */ 136 ok = midi_devs[dev]->outputc(dev, c); 137 spin_lock_irqsave(&lock, flags); 138 if (!ok) 139 break; 140 midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE; 141 midi_out_buf[dev]->len--; 142 } 143 144 if (DATA_AVAIL(midi_out_buf[dev]) < 100) 145 wake_up(&midi_sleeper[dev]); 146 } 147 poll_timer.expires = (1) + jiffies; 148 add_timer(&poll_timer); 149 /* 150 * Come back later 151 */ 152 } 153 spin_unlock_irqrestore(&lock, flags); 154} 155 156int MIDIbuf_open(int dev, struct file *file) 157{ 158 int mode, err; 159 160 dev = dev >> 4; 161 mode = translate_mode(file); 162 163 if (num_midis > MAX_MIDI_DEV) 164 { 165 printk(KERN_ERR "midi: Too many midi interfaces\n"); 166 num_midis = MAX_MIDI_DEV; 167 } 168 if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) 169 return -ENXIO; 170 /* 171 * Interrupts disabled. Be careful 172 */ 173 174 module_put(midi_devs[dev]->owner); 175 176 if ((err = midi_devs[dev]->open(dev, mode, 177 midi_input_intr, midi_output_intr)) < 0) 178 return err; 179 180 parms[dev].prech_timeout = MAX_SCHEDULE_TIMEOUT; 181 midi_in_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf)); 182 183 if (midi_in_buf[dev] == NULL) 184 { 185 printk(KERN_WARNING "midi: Can't allocate buffer\n"); 186 midi_devs[dev]->close(dev); 187 return -EIO; 188 } 189 midi_in_buf[dev]->len = midi_in_buf[dev]->head = midi_in_buf[dev]->tail = 0; 190 191 midi_out_buf[dev] = (struct midi_buf *) vmalloc(sizeof(struct midi_buf)); 192 193 if (midi_out_buf[dev] == NULL) 194 { 195 printk(KERN_WARNING "midi: Can't allocate buffer\n"); 196 midi_devs[dev]->close(dev); 197 vfree(midi_in_buf[dev]); 198 midi_in_buf[dev] = NULL; 199 return -EIO; 200 } 201 midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0; 202 open_devs++; 203 204 init_waitqueue_head(&midi_sleeper[dev]); 205 init_waitqueue_head(&input_sleeper[dev]); 206 207 if (open_devs < 2) /* This was first open */ 208 { 209 poll_timer.expires = 1 + jiffies; 210 add_timer(&poll_timer); /* Start polling */ 211 } 212 return err; 213} 214 215void MIDIbuf_release(int dev, struct file *file) 216{ 217 int mode; 218 219 dev = dev >> 4; 220 mode = translate_mode(file); 221 222 if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL) 223 return; 224 225 /* 226 * Wait until the queue is empty 227 */ 228 229 if (mode != OPEN_READ) 230 { 231 midi_devs[dev]->outputc(dev, 0xfe); /* 232 * Active sensing to shut the 233 * devices 234 */ 235 236 while (!signal_pending(current) && DATA_AVAIL(midi_out_buf[dev])) 237 interruptible_sleep_on(&midi_sleeper[dev]); 238 /* 239 * Sync 240 */ 241 242 drain_midi_queue(dev); /* 243 * Ensure the output queues are empty 244 */ 245 } 246 247 midi_devs[dev]->close(dev); 248 249 open_devs--; 250 if (open_devs == 0) 251 del_timer_sync(&poll_timer); 252 vfree(midi_in_buf[dev]); 253 vfree(midi_out_buf[dev]); 254 midi_in_buf[dev] = NULL; 255 midi_out_buf[dev] = NULL; 256 257 module_put(midi_devs[dev]->owner); 258} 259 260int MIDIbuf_write(int dev, struct file *file, const char __user *buf, int count) 261{ 262 int c, n, i; 263 unsigned char tmp_data; 264 265 dev = dev >> 4; 266 267 if (!count) 268 return 0; 269 270 c = 0; 271 272 while (c < count) 273 { 274 n = SPACE_AVAIL(midi_out_buf[dev]); 275 276 if (n == 0) { /* 277 * No space just now. 278 */ 279 280 if (file->f_flags & O_NONBLOCK) { 281 c = -EAGAIN; 282 goto out; 283 } 284 285 interruptible_sleep_on(&midi_sleeper[dev]); 286 if (signal_pending(current)) 287 { 288 c = -EINTR; 289 goto out; 290 } 291 n = SPACE_AVAIL(midi_out_buf[dev]); 292 } 293 if (n > (count - c)) 294 n = count - c; 295 296 for (i = 0; i < n; i++) 297 { 298 /* BROKE BROKE BROKE - CANT DO THIS WITH CLI !! */ 299 /* yes, think the same, so I removed the cli() brackets 300 QUEUE_BYTE is protected against interrupts */ 301 if (copy_from_user((char *) &tmp_data, &(buf)[c], 1)) { 302 c = -EFAULT; 303 goto out; 304 } 305 QUEUE_BYTE(midi_out_buf[dev], tmp_data); 306 c++; 307 } 308 } 309out: 310 return c; 311} 312 313 314int MIDIbuf_read(int dev, struct file *file, char __user *buf, int count) 315{ 316 int n, c = 0; 317 unsigned char tmp_data; 318 319 dev = dev >> 4; 320 321 if (!DATA_AVAIL(midi_in_buf[dev])) { /* 322 * No data yet, wait 323 */ 324 if (file->f_flags & O_NONBLOCK) { 325 c = -EAGAIN; 326 goto out; 327 } 328 interruptible_sleep_on_timeout(&input_sleeper[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