root/drivers/sound/soundcard.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. put_status
  2. init_status
  3. read_status
  4. snd_ioctl_return
  5. sound_read
  6. sound_write
  7. sound_lseek
  8. sound_open
  9. sound_release
  10. sound_ioctl
  11. sound_select
  12. soundcard_init
  13. tenmicrosec
  14. snd_set_irq_handler
  15. snd_release_irq
  16. request_sound_timer
  17. sound_stop_timer
  18. valid_dma_page
  19. sound_mem_init
  20. soundcard_init
  21. sound_mem_init

   1 
   2 /*
   3  * linux/kernel/chr_drv/sound/soundcard.c
   4  * 
   5  * Soundcard driver for Linux
   6  * 
   7  * Copyright by Hannu Savolainen 1993
   8  * 
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are
  11  * met: 1. Redistributions of source code must retain the above copyright
  12  * notice, this list of conditions and the following disclaimer. 2.
  13  * Redistributions in binary form must reproduce the above copyright notice,
  14  * this list of conditions and the following disclaimer in the documentation
  15  * and/or other materials provided with the distribution.
  16  * 
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  * 
  29  */
  30 
  31 #include "sound_config.h"
  32 
  33 #ifdef CONFIGURE_SOUNDCARD
  34 
  35 #include <linux/major.h>
  36 
  37 struct sbc_device
  38 {
  39   int             usecount;
  40 };
  41 
  42 static struct sbc_device sbc_devices[SND_NDEVS];
  43 extern long     seq_time;
  44 
  45 static int      in_use = 0;     /* Total # of open device files (excluding
  46                                  * minor 0) */
  47 static int      soundcards_installed = 0;       /* Number of installed
  48                                                  * soundcards */
  49 static int      soundcard_configured = 0;
  50 
  51 static struct fileinfo files[SND_NDEVS];
  52 
  53 extern char    *snd_raw_buf[MAX_DSP_DEV][DSP_BUFFCOUNT];
  54 extern unsigned long snd_raw_buf_phys[MAX_DSP_DEV][DSP_BUFFCOUNT];
  55 extern int      snd_raw_count[MAX_DSP_DEV];
  56 
  57 /*
  58  * /dev/sndstatus -device
  59  */
  60 static char    *status_buf = NULL;
  61 static int      status_len, status_ptr;
  62 static int      status_busy = 0;
  63 
  64 static int
  65 put_status (char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67   int             l = strlen (s);
  68 
  69   if (status_len + l >= 4000)
  70     return 0;
  71 
  72   memcpy (&status_buf[status_len], s, l);
  73   status_len += l;
  74 
  75   return 1;
  76 }
  77 
  78 static void
  79 init_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81   /*
  82    * Write the status information to the status_buf and update status_len.
  83    * There is a limit of 4000 bytes for the data.
  84    */
  85 
  86   char            tmp_buf[256]; /* Line buffer */
  87   int             i;
  88 
  89   status_ptr = 0;
  90 
  91   put_status ("Sound Driver:" SOUND_VERSION_STRING
  92               " (" SOUND_CONFIG_DATE " " SOUND_CONFIG_BY "@"
  93               SOUND_CONFIG_HOST "." SOUND_CONFIG_DOMAIN ")"
  94               "\n");
  95 
  96   sprintf (tmp_buf, "Config options: 0x%08x\n\n", SELECTED_SOUND_OPTIONS);
  97   if (!put_status (tmp_buf))
  98     return;
  99 
 100   sprintf (tmp_buf, "Major number: %d\n", SOUND_MAJOR);
 101   if (!put_status (tmp_buf))
 102     return;
 103 
 104   if (!put_status ("HW config: \n"))
 105     return;
 106 
 107   for (i = 0; i < (num_sound_drivers - 1); i++)
 108     {
 109       if (!supported_drivers[i].enabled) 
 110       if (!put_status ("("))
 111         return;
 112 
 113       sprintf (tmp_buf, "Type %02x: %s",
 114                supported_drivers[i].card_type,
 115                supported_drivers[i].name);
 116       if (!put_status (tmp_buf))
 117         return;
 118 
 119       sprintf (tmp_buf, " at 0x%03x irq %d drq %d",
 120                supported_drivers[i].config.io_base,
 121                supported_drivers[i].config.irq,
 122                supported_drivers[i].config.dma);
 123       if (!put_status (tmp_buf))
 124         return;
 125 
 126       if (!supported_drivers[i].enabled) 
 127       if (!put_status (")"))
 128         return;
 129 
 130       if (!put_status ("\n"))
 131         return;
 132     }
 133 
 134   if (!put_status ("\nPCM devices:\n"))
 135     return;
 136 
 137   for (i = 0; i < num_dspdevs; i++)
 138     {
 139       sprintf (tmp_buf, "%02d: %s\n", i, dsp_devs[i]->name);
 140       if (!put_status (tmp_buf))
 141         return;
 142     }
 143 
 144   if (!put_status ("\nSynth devices:\n"))
 145     return;
 146 
 147   for (i = 0; i < num_synths; i++)
 148     {
 149       sprintf (tmp_buf, "%02d: %s\n", i, synth_devs[i]->info->name);
 150       if (!put_status (tmp_buf))
 151         return;
 152     }
 153 
 154   if (!put_status ("\nMidi devices:\n"))
 155     return;
 156 
 157   for (i = 0; i < num_midis; i++)
 158     {
 159       sprintf (tmp_buf, "%02d: %s\n", i, midi_devs[i]->info.name);
 160       if (!put_status (tmp_buf))
 161         return;
 162     }
 163 
 164   if (num_mixers)
 165     {
 166       if (!put_status ("\nMixer(s) installed\n"))
 167         return;
 168     }
 169   else
 170     {
 171       if (!put_status ("\nNo mixers installed\n"))
 172         return;
 173     }
 174 }
 175 
 176 static int
 177 read_status (char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179   /*
 180    * Return at most 'count' bytes from the status_buf.
 181    */
 182   int             l, c;
 183 
 184   l = count;
 185   c = status_len - status_ptr;
 186 
 187   if (l > c)
 188     l = c;
 189   if (l <= 0)
 190     return 0;
 191 
 192   memcpy_tofs (buf, &status_buf[status_ptr], l);
 193   status_ptr += l;
 194 
 195   return l;
 196 }
 197 
 198 int
 199 snd_ioctl_return (int *addr, int value)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201   if (value < 0)
 202     return value;
 203 
 204   PUT_WORD_TO_USER (addr, 0, value);
 205   return 0;
 206 }
 207 
 208 static int
 209 sound_read (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211   int             dev;
 212 
 213   dev = inode->i_rdev;
 214   dev = MINOR (dev);
 215 
 216   DEB (printk ("sound_read(dev=%d, count=%d)\n", dev, count));
 217 
 218   switch (dev & 0x0f)
 219     {
 220     case SND_DEV_STATUS:
 221       return read_status (buf, count);
 222       break;
 223 
 224     case SND_DEV_DSP:
 225     case SND_DEV_DSP16:
 226     case SND_DEV_AUDIO:
 227       return audio_read (dev, &files[dev], buf, count);
 228       break;
 229 
 230     case SND_DEV_SEQ:
 231       return sequencer_read (dev, &files[dev], buf, count);
 232       break;
 233 
 234 #ifndef EXCLUDE_MPU401
 235     case SND_DEV_MIDIN:
 236       return MIDIbuf_read (dev, &files[dev], buf, count);
 237 #endif
 238 
 239     default:
 240       printk ("Sound: Undefined minor device %d\n", dev);
 241     }
 242 
 243   return RET_ERROR (EPERM);
 244 }
 245 
 246 static int
 247 sound_write (struct inode *inode, struct file *file, char *buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249   int             dev;
 250 
 251   dev = inode->i_rdev;
 252   dev = MINOR (dev);
 253 
 254   DEB (printk ("sound_write(dev=%d, count=%d)\n", dev, count));
 255 
 256   switch (dev & 0x0f)
 257     {
 258 
 259     case SND_DEV_SEQ:
 260       return sequencer_write (dev, &files[dev], buf, count);
 261       break;
 262 
 263     case SND_DEV_DSP:
 264     case SND_DEV_DSP16:
 265     case SND_DEV_AUDIO:
 266       return audio_write (dev, &files[dev], buf, count);
 267       break;
 268 
 269     default:
 270       return RET_ERROR (EPERM);
 271     }
 272 
 273   return count;
 274 }
 275 
 276 static int
 277 sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279   return RET_ERROR (EPERM);
 280 }
 281 
 282 static int
 283 sound_open (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 284 {
 285   int             dev, retval;
 286 
 287   dev = inode->i_rdev;
 288   dev = MINOR (dev);
 289 
 290   DEB (printk ("sound_open(dev=%d) : usecount=%d\n", dev, sbc_devices[dev].usecount));
 291 
 292   if ((dev >= SND_NDEVS) || (dev < 0))
 293     {
 294       printk ("Invalid minor device %d\n", dev);
 295       return RET_ERROR (ENODEV);
 296     }
 297 
 298   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
 299     {
 300       printk ("SoundCard Error: The soundcard system has not been configured\n");
 301       return RET_ERROR (ENODEV);
 302     }
 303 
 304   files[dev].mode = 0;
 305 
 306   if ((file->f_flags & O_ACCMODE) == O_RDWR)
 307     files[dev].mode = OPEN_READWRITE;
 308   if ((file->f_flags & O_ACCMODE) == O_RDONLY)
 309     files[dev].mode = OPEN_READ;
 310   if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 311     files[dev].mode = OPEN_WRITE;
 312 
 313   switch (dev & 0x0f)
 314     {
 315     case SND_DEV_STATUS:
 316       if (status_busy)
 317         return RET_ERROR (EBUSY);
 318       status_busy = 1;
 319       if ((status_buf = (char *) KERNEL_MALLOC (4000)) == NULL)
 320         return RET_ERROR (EIO);
 321       status_len = status_ptr = 0;
 322       init_status ();
 323       break;
 324 
 325     case SND_DEV_CTL:
 326       if (!soundcards_installed)
 327         if (soundcard_configured)
 328           {
 329             printk ("Soundcard not installed\n");
 330             return RET_ERROR (ENODEV);
 331           }
 332       break;
 333 
 334     case SND_DEV_SEQ:
 335       if ((retval = sequencer_open (dev, &files[dev])) < 0)
 336         return retval;
 337       break;
 338 
 339 #ifndef EXCLUDE_MPU401
 340     case SND_DEV_MIDIN:
 341       if ((retval = MIDIbuf_open (dev, &files[dev])) < 0)
 342         return retval;
 343       break;
 344 #endif
 345 
 346     case SND_DEV_DSP:
 347     case SND_DEV_DSP16:
 348     case SND_DEV_AUDIO:
 349       if ((retval = audio_open (dev, &files[dev])) < 0)
 350         return retval;
 351       break;
 352 
 353     default:
 354       printk ("Invalid minor device %d\n", dev);
 355       return RET_ERROR (ENODEV);
 356     }
 357 
 358   sbc_devices[dev].usecount++;
 359   in_use++;
 360 
 361   return 0;
 362 }
 363 
 364 static void
 365 sound_release (struct inode *inode, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 366 {
 367   int             dev;
 368 
 369   dev = inode->i_rdev;
 370   dev = MINOR (dev);
 371 
 372   DEB (printk ("sound_release(dev=%d)\n", dev));
 373 
 374   switch (dev & 0x0f)
 375     {
 376     case SND_DEV_STATUS:
 377       if (status_buf)
 378         KERNEL_FREE (status_buf);
 379       status_buf = NULL;
 380       status_busy = 0;
 381       break;
 382 
 383     case SND_DEV_CTL:
 384       break;
 385 
 386     case SND_DEV_SEQ:
 387       sequencer_release (dev, &files[dev]);
 388       break;
 389 
 390 #ifndef EXCLUDE_MPU401
 391     case SND_DEV_MIDIN:
 392       MIDIbuf_release (dev, &files[dev]);
 393       break;
 394 #endif
 395 
 396     case SND_DEV_DSP:
 397     case SND_DEV_DSP16:
 398     case SND_DEV_AUDIO:
 399       audio_release (dev, &files[dev]);
 400       break;
 401 
 402     default:
 403       printk ("Sound error: Releasing unknown device 0x%02x\n", dev);
 404     }
 405 
 406   sbc_devices[dev].usecount--;
 407   in_use--;
 408 }
 409 
 410 static int
 411 sound_ioctl (struct inode *inode, struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
 412              unsigned int cmd, unsigned long arg)
 413 {
 414   int             dev;
 415 
 416   dev = inode->i_rdev;
 417   dev = MINOR (dev);
 418 
 419   DEB (printk ("sound_ioctl(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 420 
 421   switch (dev & 0x0f)
 422     {
 423 
 424     case SND_DEV_CTL:
 425 
 426       if (!num_mixers)
 427         return RET_ERROR (ENODEV);
 428 
 429       if (dev >= num_mixers)
 430         return RET_ERROR (ENODEV);
 431 
 432       return mixer_devs[dev]->ioctl (dev, cmd, arg);
 433       break;
 434 
 435     case SND_DEV_SEQ:
 436       return sequencer_ioctl (dev, &files[dev], cmd, arg);
 437       break;
 438 
 439     case SND_DEV_DSP:
 440     case SND_DEV_DSP16:
 441     case SND_DEV_AUDIO:
 442       return audio_ioctl (dev, &files[dev], cmd, arg);
 443       break;
 444 
 445 #ifndef EXCLUDE_MPU401
 446     case SND_DEV_MIDIN:
 447       return MIDIbuf_ioctl (dev, &files[dev], cmd, arg);
 448       break;
 449 #endif
 450 
 451     default:
 452       return RET_ERROR (EPERM);
 453       break;
 454     }
 455 
 456   return RET_ERROR (EPERM);
 457 }
 458 
 459 static int
 460 sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462   int             dev;
 463 
 464   dev = inode->i_rdev;
 465   dev = MINOR (dev);
 466 
 467   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
 468 
 469   switch (dev & 0x0f)
 470     {
 471     case SND_DEV_SEQ:
 472       return sequencer_select (dev, &files[dev], sel_type, wait);
 473       break;
 474 
 475     default:
 476       return 0;
 477     }
 478 
 479   return 0;
 480 }
 481 
 482 static struct file_operations sound_fops =
 483 {
 484   sound_lseek,
 485   sound_read,
 486   sound_write,
 487   NULL,                         /* sound_readdir */
 488   sound_select,
 489   sound_ioctl,
 490   NULL,
 491   sound_open,
 492   sound_release
 493 };
 494 
 495 long
 496 soundcard_init (long mem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
 497 {
 498   int             i;
 499 
 500   register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
 501 
 502   soundcard_configured = 1;
 503 
 504   mem_start = sndtable_init (mem_start);        /* Initialize call tables and
 505                                                  * detect cards */
 506 
 507   if (!(soundcards_installed = sndtable_get_cardcount ()))
 508     return mem_start;           /* No cards detected */
 509 
 510   if (num_dspdevs)              /* Audio devices present */
 511     {
 512       mem_start = DMAbuf_init (mem_start);
 513       mem_start = audio_init (mem_start);
 514     }
 515 
 516 #ifndef EXCLUDE_MPU401
 517   if (num_midis)
 518     mem_start = MIDIbuf_init (mem_start);
 519 #endif
 520 
 521   if (num_midis + num_synths)
 522     mem_start = sequencer_init (mem_start);
 523 
 524   for (i = 0; i < SND_NDEVS; i++)
 525     {
 526       sbc_devices[i].usecount = 0;
 527     }
 528 
 529   return mem_start;
 530 }
 531 
 532 void
 533 tenmicrosec (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535   int             i;
 536 
 537   for (i = 0; i < 16; i++)
 538     inb (0x80);
 539 }
 540 
 541 int
 542 snd_set_irq_handler (int interrupt_level, void(*hndlr)(int))
     /* [previous][next][first][last][top][bottom][index][help] */
 543 {
 544   int             retcode;
 545 
 546   struct sigaction sa;
 547 
 548   sa.sa_handler = hndlr;
 549 
 550 #ifdef SND_SA_INTERRUPT
 551   sa.sa_flags = SA_INTERRUPT;
 552 #else
 553   sa.sa_flags = 0;
 554 #endif
 555 
 556   sa.sa_mask = 0;
 557   sa.sa_restorer = NULL;
 558 
 559   retcode = irqaction (interrupt_level, &sa);
 560 
 561   if (retcode < 0)
 562     {
 563       printk ("Sound: IRQ%d already in use\n", interrupt_level);
 564     }
 565 
 566   return retcode;
 567 }
 568 
 569 void
 570 snd_release_irq(int vect)
     /* [previous][next][first][last][top][bottom][index][help] */
 571 {
 572         free_irq(vect);
 573 }
 574 
 575 void
 576 request_sound_timer (int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 577 {
 578 #ifndef EXCLUDE_SEQUENCER
 579   if (count < 0)
 580     count = jiffies + (-count);
 581   else
 582     count += seq_time;
 583   timer_table[SOUND_TIMER].fn = sequencer_timer;
 584   timer_table[SOUND_TIMER].expires = count;
 585   timer_active |= 1 << SOUND_TIMER;
 586 #endif
 587 }
 588 
 589 void
 590 sound_stop_timer (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 591 {
 592 #ifndef EXCLUDE_SEQUENCER
 593   timer_table[SOUND_TIMER].expires = 0;
 594   timer_active &= ~(1 << SOUND_TIMER);
 595 #endif
 596 }
 597 
 598 #ifndef EXCLUDE_AUDIO
 599 static int
 600 valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
     /* [previous][next][first][last][top][bottom][index][help] */
 601 {
 602   if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
 603     return 1;
 604   else
 605     return 0;
 606 }
 607 
 608 void
 609 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 610 {
 611   int             i, dev;
 612   unsigned long   start_addr, end_addr, mem_ptr, dma_pagesize;
 613 
 614   mem_ptr = high_memory;
 615 
 616   /* Some sanity checks */
 617 
 618   if (mem_ptr > (16 * 1024 * 1024))
 619     mem_ptr = 16 * 1024 * 1024; /* Limit to 16M */
 620 
 621   for (dev = 0; dev < num_dspdevs; dev++)       /* Enumerate devices */
 622     if (sound_buffcounts[dev] > 0 && sound_dsp_dmachan[dev] > 0)
 623       {
 624         if (sound_dma_automode[dev])
 625           sound_buffcounts[dev] = 1;
 626 
 627         if (sound_dsp_dmachan[dev] > 3 && sound_buffsizes[dev] > 65536)
 628           dma_pagesize = 131072;/* 128k */
 629         else
 630           dma_pagesize = 65536;
 631 
 632         /* More sanity checks */
 633 
 634         if (sound_buffsizes[dev] > dma_pagesize)
 635           sound_buffsizes[dev] = dma_pagesize;
 636         sound_buffsizes[dev] &= 0xfffff000;     /* Truncate to n*4k */
 637         if (sound_buffsizes[dev] < 4096)
 638           sound_buffsizes[dev] = 4096;
 639 
 640         /* Now allocate the buffers */
 641 
 642         for (snd_raw_count[dev] = 0; snd_raw_count[dev] < sound_buffcounts[dev]; snd_raw_count[dev]++)
 643           {
 644             start_addr = mem_ptr - sound_buffsizes[dev];
 645             if (!valid_dma_page (start_addr, sound_buffsizes[dev], dma_pagesize))
 646               start_addr &= ~(dma_pagesize - 1);        /* Align address to
 647                                                          * dma_pagesize */
 648 
 649             end_addr = start_addr + sound_buffsizes[dev] - 1;
 650 
 651             snd_raw_buf[dev][snd_raw_count[dev]] = (char *) start_addr;
 652             snd_raw_buf_phys[dev][snd_raw_count[dev]] = start_addr;
 653             mem_ptr = start_addr;
 654 
 655             for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
 656               {
 657                 if (mem_map[i])
 658                   panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
 659 
 660                 mem_map[i] = MAP_PAGE_RESERVED;
 661               }
 662           }
 663       }                         /* for dev */
 664 }
 665 
 666 #endif
 667 
 668 #else
 669 
 670 long
 671 soundcard_init (long mem_start) /* Dummy version */
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673   return mem_start;
 674 }
 675 
 676 #endif
 677 
 678 #if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
 679 void
 680 sound_mem_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 681 {
 682   /* Dummy version */
 683 }
 684 
 685 #endif

/* [previous][next][first][last][top][bottom][index][help] */