This source file includes following definitions.
- snd_ioctl_return
- sound_read
- sound_write
- sound_lseek
- sound_open
- sound_release
- sound_ioctl
- sound_select
- soundcard_init
- free_all_irqs
- init_module
- cleanup_module
- tenmicrosec
- snd_set_irq_handler
- snd_release_irq
- request_sound_timer
- sound_stop_timer
- valid_dma_page
- add_to_dma_list
- module_sound_mem_init
- module_sound_mem_release
- sound_mem_init
- soundcard_init
- sound_mem_init
- module_sound_mem_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include "sound_config.h"
34
35 #ifdef CONFIGURE_SOUNDCARD
36
37 #include <linux/major.h>
38
39 static int soundcards_installed = 0;
40
41
42 static int soundcard_configured = 0;
43
44 static struct fileinfo files[SND_NDEVS];
45
46 int
47 snd_ioctl_return (int *addr, int value)
48 {
49 if (value < 0)
50 return value;
51
52 PUT_WORD_TO_USER (addr, 0, value);
53 return 0;
54 }
55
56 static int
57 sound_read (struct inode *inode, struct file *file, char *buf, int count)
58 {
59 int dev;
60
61 dev = inode->i_rdev;
62 dev = MINOR (dev);
63
64 return sound_read_sw (dev, &files[dev], buf, count);
65 }
66
67 static int
68 sound_write (struct inode *inode, struct file *file, char *buf, int count)
69 {
70 int dev;
71
72 #ifdef MODULE
73 int err;
74
75 #endif
76
77 dev = inode->i_rdev;
78 dev = MINOR (dev);
79
80 return sound_write_sw (dev, &files[dev], buf, count);
81 }
82
83 static int
84 sound_lseek (struct inode *inode, struct file *file, off_t offset, int orig)
85 {
86 return RET_ERROR (EPERM);
87 }
88
89 static int
90 sound_open (struct inode *inode, struct file *file)
91 {
92 int dev, retval;
93 struct fileinfo tmp_file;
94
95 dev = inode->i_rdev;
96 dev = MINOR (dev);
97
98 if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
99 {
100 printk ("SoundCard Error: The soundcard system has not been configured\n");
101 return RET_ERROR (ENXIO);
102 }
103
104 tmp_file.mode = 0;
105 tmp_file.filp = file;
106
107 if ((file->f_flags & O_ACCMODE) == O_RDWR)
108 tmp_file.mode = OPEN_READWRITE;
109 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
110 tmp_file.mode = OPEN_READ;
111 if ((file->f_flags & O_ACCMODE) == O_WRONLY)
112 tmp_file.mode = OPEN_WRITE;
113
114 if ((retval = sound_open_sw (dev, &tmp_file)) < 0)
115 return retval;
116
117 #ifdef MODULE
118 MOD_INC_USE_COUNT;
119 #endif
120
121 memcpy ((char *) &files[dev], (char *) &tmp_file, sizeof (tmp_file));
122 return retval;
123 }
124
125 static void
126 sound_release (struct inode *inode, struct file *file)
127 {
128 int dev;
129
130 dev = inode->i_rdev;
131 dev = MINOR (dev);
132
133 sound_release_sw (dev, &files[dev]);
134 #ifdef MODULE
135 MOD_DEC_USE_COUNT;
136 #endif
137 }
138
139 static int
140 sound_ioctl (struct inode *inode, struct file *file,
141 unsigned int cmd, unsigned long arg)
142 {
143 int dev;
144
145 dev = inode->i_rdev;
146 dev = MINOR (dev);
147
148 if (cmd & IOC_INOUT)
149 {
150
151
152
153 int len, err;
154
155 len = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
156
157 if (cmd & IOC_IN)
158 {
159 if ((err = verify_area (VERIFY_READ, (void *) arg, len)) < 0)
160 return err;
161 }
162
163 if (cmd & IOC_OUT)
164 {
165 if ((err = verify_area (VERIFY_WRITE, (void *) arg, len)) < 0)
166 return err;
167 }
168
169 }
170
171 return sound_ioctl_sw (dev, &files[dev], cmd, arg);
172 }
173
174 static int
175 sound_select (struct inode *inode, struct file *file, int sel_type, select_table * wait)
176 {
177 int dev;
178
179 dev = inode->i_rdev;
180 dev = MINOR (dev);
181
182 DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
183
184 switch (dev & 0x0f)
185 {
186 #ifndef EXCLUDE_SEQUENCER
187 case SND_DEV_SEQ:
188 case SND_DEV_SEQ2:
189 return sequencer_select (dev, &files[dev], sel_type, wait);
190 break;
191 #endif
192
193 #ifndef EXCLUDE_MIDI
194 case SND_DEV_MIDIN:
195 return MIDIbuf_select (dev, &files[dev], sel_type, wait);
196 break;
197 #endif
198
199 #ifndef EXCLUDE_AUDIO
200 case SND_DEV_DSP:
201 case SND_DEV_DSP16:
202 case SND_DEV_AUDIO:
203 return audio_select (dev, &files[dev], sel_type, wait);
204 break;
205 #endif
206
207 default:
208 return 0;
209 }
210
211 return 0;
212 }
213
214 static struct file_operations sound_fops =
215 {
216 sound_lseek,
217 sound_read,
218 sound_write,
219 NULL,
220 sound_select,
221 sound_ioctl,
222 NULL,
223 sound_open,
224 sound_release
225 };
226
227 long
228 soundcard_init (long mem_start)
229 {
230 #ifndef MODULE
231 register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
232 #endif
233
234 soundcard_configured = 1;
235
236 mem_start = sndtable_init (mem_start);
237
238
239 if (!(soundcards_installed = sndtable_get_cardcount ()))
240 return mem_start;
241
242 #ifndef EXCLUDE_AUDIO
243 if (num_audiodevs)
244 {
245 mem_start = DMAbuf_init (mem_start);
246 mem_start = audio_init (mem_start);
247 }
248 #endif
249
250 #ifndef EXCLUDE_MIDI
251 if (num_midis)
252 mem_start = MIDIbuf_init (mem_start);
253 #endif
254
255 #ifndef EXCLUDE_SEQUENCER
256 if (num_midis + num_synths)
257 mem_start = sequencer_init (mem_start);
258 #endif
259
260 return mem_start;
261 }
262
263 #ifdef MODULE
264 static unsigned long irqs = 0;
265 void snd_release_irq (int);
266 static int module_sound_mem_init (void);
267 static void module_sound_mem_release (void);
268
269 static void
270 free_all_irqs (void)
271 {
272 int i;
273
274 for (i = 0; i < 31; i++)
275 if (irqs & (1ul << i))
276 snd_release_irq (i);
277 irqs = 0;
278 }
279
280 char kernel_version[] = UTS_RELEASE;
281
282 static long memory_pool = 0;
283 static int memsize = 70 * 1024;
284 static int debugmem = 0;
285
286 int
287 init_module (void)
288 {
289 long lastbyte;
290 int err;
291
292 printk ("sound: made modular by Peter Trattler (peter@sbox.tu-graz.ac.at)\n");
293 err = register_chrdev (SOUND_MAJOR, "sound", &sound_fops);
294 if (err)
295 {
296 printk ("sound: driver already loaded/included in kernel\n");
297 return err;
298 }
299 memory_pool = (long) kmalloc (memsize, GFP_KERNEL);
300 if (memory_pool == 0l)
301 {
302 unregister_chrdev (SOUND_MAJOR, "sound");
303 return -ENOMEM;
304 }
305 lastbyte = soundcard_init (memory_pool);
306 if (lastbyte > memory_pool + memsize)
307 {
308 printk ("sound: Not enough memory; use : 'insmod sound.o memsize=%ld'\n",
309 lastbyte - memory_pool);
310 kfree ((void *) memory_pool);
311 unregister_chrdev (SOUND_MAJOR, "sound");
312 free_all_irqs ();
313 return -ENOMEM;
314 }
315 err = module_sound_mem_init ();
316 if (err)
317 {
318 module_sound_mem_release ();
319 kfree ((void *) memory_pool);
320 unregister_chrdev (SOUND_MAJOR, "sound");
321 free_all_irqs ();
322 return err;
323 }
324 if (lastbyte < memory_pool + memsize)
325 printk ("sound: (Suggestion) too much memory; use : 'insmod sound.o memsize=%ld'\n",
326 lastbyte - memory_pool);
327 return 0;
328 }
329
330 void
331 cleanup_module (void)
332 {
333 if (MOD_IN_USE)
334 printk ("sound: module busy -- remove delayed\n");
335 else
336 {
337 kfree ((void *) memory_pool);
338 unregister_chrdev (SOUND_MAJOR, "sound");
339 free_all_irqs ();
340 module_sound_mem_release ();
341 }
342 }
343
344 #endif
345
346 void
347 tenmicrosec (void)
348 {
349 int i;
350
351 for (i = 0; i < 16; i++)
352 inb (0x80);
353 }
354
355 int
356 snd_set_irq_handler (int interrupt_level, INT_HANDLER_PROTO (), char *name)
357 {
358 int retcode;
359
360 retcode = request_irq (interrupt_level, hndlr, SA_INTERRUPT, name);
361 if (retcode < 0)
362 {
363 printk ("Sound: IRQ%d already in use\n", interrupt_level);
364 }
365 #ifdef MODULE
366 else
367 irqs |= (1ul << interrupt_level);
368 #endif
369
370 return retcode;
371 }
372
373 void
374 snd_release_irq (int vect)
375 {
376 #ifdef MODULE
377 irqs &= ~(1ul << vect);
378 #endif
379 free_irq (vect);
380 }
381
382 #ifndef EXCLUDE_SEQUENCER
383 void
384 request_sound_timer (int count)
385 {
386 extern unsigned long seq_time;
387
388 #if 1
389 if (count < 0)
390 count = jiffies + (-count);
391 else
392 count += seq_time;
393 timer_table[SOUND_TIMER].fn = sequencer_timer;
394 timer_table[SOUND_TIMER].expires = count;
395 timer_active |= 1 << SOUND_TIMER;
396 #endif
397 }
398
399 #endif
400
401 void
402 sound_stop_timer (void)
403 {
404 #if 1
405 timer_table[SOUND_TIMER].expires = 0;
406 timer_active &= ~(1 << SOUND_TIMER);
407 #endif
408 }
409
410 #ifndef EXCLUDE_AUDIO
411 static int
412 valid_dma_page (unsigned long addr, unsigned long dev_buffsize, unsigned long dma_pagesize)
413 {
414 if (((addr & (dma_pagesize - 1)) + dev_buffsize) <= dma_pagesize)
415 return 1;
416 else
417 return 0;
418 }
419
420 #ifdef MODULE
421
422 #ifdef KMALLOC_DMA_BROKEN
423 #define KMALLOC_MEM_REGIONS 20
424
425 static char *dma_list[KMALLOC_MEM_REGIONS];
426 static int dma_last = 0;
427 inline void
428 add_to_dma_list (char *adr)
429 {
430 dma_list[dma_last++] = adr;
431 }
432
433 #endif
434
435 static int
436 module_sound_mem_init (void)
437 {
438 int dev, ret = 0;
439 unsigned long dma_pagesize;
440 char *start_addr, *end_addr;
441 struct dma_buffparms *dmap;
442
443 for (dev = 0; dev < num_audiodevs; dev++)
444 if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
445 {
446 dmap = audio_devs[dev]->dmap;
447 if (audio_devs[dev]->flags & DMA_AUTOMODE)
448 audio_devs[dev]->buffcount = 1;
449
450 if (audio_devs[dev]->dmachan > 3)
451 dma_pagesize = 131072;
452 else
453 dma_pagesize = 65536;
454 if (debugmem)
455 printk ("sound: dma-page-size %lu\n", dma_pagesize);
456
457
458 if (audio_devs[dev]->buffsize > dma_pagesize)
459 audio_devs[dev]->buffsize = dma_pagesize;
460 audio_devs[dev]->buffsize &= 0xfffff000;
461 if (audio_devs[dev]->buffsize < 4096)
462 audio_devs[dev]->buffsize = 4096;
463 if (debugmem)
464 printk ("sound: buffsize %lu\n", audio_devs[dev]->buffsize);
465
466 for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount;
467 dmap->raw_count++)
468 {
469 #ifdef KMALLOC_DMA_BROKEN
470 start_addr = kmalloc (audio_devs[dev]->buffsize, GFP_KERNEL);
471 if (start_addr)
472 {
473 if (debugmem)
474 printk ("sound: trying 0x%lx for DMA\n", (long) start_addr);
475 if (valid_dma_page ((unsigned long) start_addr,
476 audio_devs[dev]->buffsize,
477 dma_pagesize))
478 add_to_dma_list (start_addr);
479 else
480 {
481 kfree (start_addr);
482 start_addr = kmalloc (audio_devs[dev]->buffsize * 2,
483 GFP_KERNEL);
484 if (start_addr)
485 {
486 if (debugmem)
487 printk ("sound: failed; trying 0x%lx aligned to",
488 (long) start_addr);
489 add_to_dma_list (start_addr);
490
491 start_addr = (char *) (((long) start_addr
492 + dma_pagesize - 1)
493 & ~(dma_pagesize - 1));
494 if (debugmem)
495 printk (" 0x%lx\n", (long) start_addr);
496 }
497 }
498 }
499 #else
500 start_addr = kmalloc (audio_devs[dev]->buffsize,
501 GFP_DMA | GFP_KERNEL);
502 #endif
503 if (start_addr == NULL)
504 ret = -ENOMEM;
505
506
507
508 else
509 {
510
511 end_addr = start_addr + audio_devs[dev]->buffsize - 1;
512 if (debugmem)
513 printk ("sound: start 0x%lx, end 0x%lx\n",
514 (long) start_addr, (long) end_addr);
515
516 if (((long) start_addr & ~(dma_pagesize - 1))
517 != ((long) end_addr & ~(dma_pagesize - 1))
518 || end_addr >= (char *) (16 * 1024 * 1024))
519 {
520 printk (
521 "sound: kmalloc returned invalid address 0x%lx for %ld Bytes DMA-buffer\n",
522 (long) start_addr,
523 audio_devs[dev]->buffsize);
524 ret = -EFAULT;
525 }
526 }
527 dmap->raw_buf[dmap->raw_count] = start_addr;
528 dmap->raw_buf_phys[dmap->raw_count] = (unsigned long) start_addr;
529 }
530 }
531 return ret;
532 }
533
534 static void
535 module_sound_mem_release (void)
536 {
537 #ifdef KMALLOC_DMA_BROKEN
538 int i;
539
540 for (i = 0; i < dma_last; i++)
541 {
542 if (debugmem)
543 printk ("sound: freeing 0x%lx\n", (long) dma_list[i]);
544 kfree (dma_list[i]);
545 }
546 #else
547 int dev, i;
548
549 for (dev = 0; dev < num_audiodevs; dev++)
550 if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
551 {
552 for (i = 0; i < audio_devs[dev]->buffcount; i++)
553 if (audio_devs[dev]->dmap->raw_buf[i])
554 {
555 if (debugmem)
556 printk ("sound: freeing 0x%lx\n",
557 (long) (audio_devs[dev]->dmap->raw_buf[i]));
558 kfree (audio_devs[dev]->dmap->raw_buf[i]);
559 }
560 }
561 #endif
562 }
563
564 #else
565
566 void
567 sound_mem_init (void)
568 {
569 int i, dev;
570 unsigned long start_addr, end_addr, mem_ptr, dma_pagesize;
571 struct dma_buffparms *dmap;
572
573 mem_ptr = high_memory;
574
575
576
577 if (mem_ptr > (16 * 1024 * 1024))
578 mem_ptr = 16 * 1024 * 1024;
579
580 for (dev = 0; dev < num_audiodevs; dev++)
581 if (audio_devs[dev]->buffcount > 0 && audio_devs[dev]->dmachan >= 0)
582 {
583 dmap = audio_devs[dev]->dmap;
584
585 if (audio_devs[dev]->flags & DMA_AUTOMODE)
586 audio_devs[dev]->buffcount = 1;
587
588 if (audio_devs[dev]->dmachan > 3 && audio_devs[dev]->buffsize > 65536)
589 dma_pagesize = 131072;
590 else
591 dma_pagesize = 65536;
592
593
594
595 if (audio_devs[dev]->buffsize > dma_pagesize)
596 audio_devs[dev]->buffsize = dma_pagesize;
597 audio_devs[dev]->buffsize &= 0xfffff000;
598 if (audio_devs[dev]->buffsize < 4096)
599 audio_devs[dev]->buffsize = 4096;
600
601
602
603 for (dmap->raw_count = 0; dmap->raw_count < audio_devs[dev]->buffcount; dmap->raw_count++)
604 {
605 start_addr = mem_ptr - audio_devs[dev]->buffsize;
606 if (!valid_dma_page (start_addr, audio_devs[dev]->buffsize, dma_pagesize))
607 start_addr &= ~(dma_pagesize - 1);
608
609
610 end_addr = start_addr + audio_devs[dev]->buffsize - 1;
611
612 dmap->raw_buf[dmap->raw_count] = (char *) start_addr;
613 dmap->raw_buf_phys[dmap->raw_count] = start_addr;
614 mem_ptr = start_addr;
615
616 for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
617 {
618 if (mem_map[i])
619 panic ("sound_mem_init: Page not free (driver incompatible with kernel).\n");
620
621 mem_map[i] = MAP_PAGE_RESERVED;
622 }
623 }
624 }
625 }
626
627 #endif
628
629 #endif
630
631 #else
632
633 long
634 soundcard_init (long mem_start)
635 {
636 return mem_start;
637 }
638
639 #endif
640
641 #if !defined(CONFIGURE_SOUNDCARD) || defined(EXCLUDE_AUDIO)
642 void
643 sound_mem_init (void)
644 {
645
646 }
647
648 #ifdef MODULE
649 static int
650 module_sound_mem_init (void)
651 {
652 return 0;
653 }
654
655 #endif
656
657 #endif