source: GPL/branches/uniaud32-next/lib32/misc.c@ 615

Last change on this file since 615 was 615, checked in by Paul Smedley, 5 years ago

Add source for uniaud32 based on code from linux kernel 5.4.86

File size: 23.9 KB
Line 
1/* $Id: misc.c,v 1.1.1.1 2003/07/02 13:57:02 eleph Exp $ */
2/*
3 * OS/2 implementation of misc. Linux kernel services
4 *
5 * (C) 2000-2002 InnoTek Systemberatung GmbH
6 * (C) 2000-2001 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * hweight32 based on Linux code (bitops.h)
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
23 * USA.
24 *
25 */
26#include <limits.h>
27#include "linux.h"
28#include <linux/init.h>
29#include <linux/fs.h>
30#include <linux/poll.h>
31#define CONFIG_PROC_FS 1
32#include <linux/proc_fs.h>
33#include <asm/uaccess.h>
34#include <asm/hardirq.h>
35#include <linux\ioport.h>
36#include <linux\utsname.h>
37#include <linux\module.h>
38#include <linux/workqueue.h>
39#include <linux/firmware.h>
40#include <linux/ctype.h>
41#include <dbgos2.h>
42
43void StringOut(char *DbgStr);
44
45struct new_utsname system_utsname = {0};
46struct resource ioport_resource = {NULL, 0, 0, IORESOURCE_IO, NULL, NULL, NULL};
47struct resource iomem_resource = {NULL, 0, 0, IORESOURCE_MEM, NULL, NULL, NULL};
48mem_map_t *mem_map = 0;
49int this_module[64] = {0};
50
51#include <stdarg.h>
52
53char szLastALSAError1[128] = {0};
54char szOverrunTest1 = 0xCC;
55char szLastALSAError2[128] = {0};
56char szOverrunTest2 = 0xCC;
57int iLastError = 0;
58
59//******************************************************************************
60//Save error message in szLastALSAError; if card init failed, then we will
61//print it in drv32\init.cpp
62//******************************************************************************
63int printk(const char * fmt, ...)
64{
65 va_list argptr; /* -> variable argument list */
66
67 char *pszLastALSAError;
68
69 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
70
71 va_start(argptr, fmt); /* get pointer to argument list */
72 vsprintf(pszLastALSAError, fmt, argptr);
73// strcat(pszLastALSAError, "\r");
74 va_end(argptr); /* done with variable arguments */
75
76 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
77 DebugInt3();
78 }
79
80 StringOut(pszLastALSAError);
81// rprintf( (pszLastALSAError) );
82 if(++iLastError > 1) {
83 iLastError = 0;
84 }
85 return 0;
86}
87
88//******************************************************************************
89//Save error message in szLastALSAError; if card init failed, then we will
90//print it in drv32\init.cpp
91//******************************************************************************
92int dev_dbg(const struct device *dev, const char * fmt, ...)
93{
94 va_list argptr; /* -> variable argument list */
95
96 char *pszLastALSAError;
97
98 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
99
100 va_start(argptr, fmt); /* get pointer to argument list */
101 vsprintf(pszLastALSAError, fmt, argptr);
102// strcat(pszLastALSAError, "\r");
103 va_end(argptr); /* done with variable arguments */
104
105 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
106 DebugInt3();
107 }
108
109 StringOut(pszLastALSAError);
110// rprintf( (pszLastALSAError) );
111 if(++iLastError > 1) {
112 iLastError = 0;
113 }
114 return 0;
115}
116//******************************************************************************
117int pcm_dbg(struct snd_pcm *dev, const char * fmt, ...)
118{
119 va_list argptr; /* -> variable argument list */
120
121 char *pszLastALSAError;
122
123 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
124
125 va_start(argptr, fmt); /* get pointer to argument list */
126 vsprintf(pszLastALSAError, fmt, argptr);
127// strcat(pszLastALSAError, "\r");
128 va_end(argptr); /* done with variable arguments */
129
130 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
131 DebugInt3();
132 }
133
134 StringOut(pszLastALSAError);
135// rprintf( (pszLastALSAError) );
136 if(++iLastError > 1) {
137 iLastError = 0;
138 }
139 return 0;
140}
141//******************************************************************************
142int codec_dbg(struct hda_codec *dev, const char * fmt, ...)
143{
144 va_list argptr; /* -> variable argument list */
145
146 char *pszLastALSAError;
147
148 pszLastALSAError= iLastError ? szLastALSAError2 : szLastALSAError1;
149
150 va_start(argptr, fmt); /* get pointer to argument list */
151 vsprintf(pszLastALSAError, fmt, argptr);
152// strcat(pszLastALSAError, "\r");
153 va_end(argptr); /* done with variable arguments */
154
155 if(szOverrunTest1 != 0xCC || szOverrunTest2 != 0xCC) {
156 DebugInt3();
157 }
158
159 StringOut(pszLastALSAError);
160// rprintf( (pszLastALSAError) );
161 if(++iLastError > 1) {
162 iLastError = 0;
163 }
164 return 0;
165}
166//******************************************************************************
167//******************************************************************************
168void schedule(void)
169{
170
171}
172//******************************************************************************
173//******************************************************************************
174void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
175{
176
177}
178//******************************************************************************
179//******************************************************************************
180int __check_region(struct resource *a, unsigned long b, unsigned long c)
181{
182 DebugInt3();
183 return 0;
184}
185
186/* --------------------------------------------------------------------- */
187/*
188 * hweightN: returns the hamming weight (i.e. the number
189 * of bits set) of a N-bit word
190 */
191
192#ifdef hweight32
193#undef hweight32
194#endif
195
196unsigned int hweight32(unsigned int w)
197{
198 unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
199 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
200 res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
201 res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
202 return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
203}
204//******************************************************************************
205//******************************************************************************
206#if 0
207mem_map_t *virt_to_page(int x)
208{
209 static mem_map_t map = {0};
210 return &map;
211}
212#endif
213//******************************************************************************
214//******************************************************************************
215struct proc_dir_entry proc_root = {0};
216//******************************************************************************
217//******************************************************************************
218struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
219 struct proc_dir_entry *parent)
220{
221 struct proc_dir_entry *proc;
222 proc = (struct proc_dir_entry *)kmalloc(sizeof(struct proc_dir_entry), 0);
223 memset(proc, 0, sizeof(struct proc_dir_entry));
224
225 proc->name = name;
226 proc->mode = mode;
227 proc->parent = parent;
228
229 return proc;
230}
231//******************************************************************************
232//******************************************************************************
233void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
234{
235 return; //memory leak
236}
237//******************************************************************************
238//******************************************************************************
239int proc_register(struct proc_dir_entry *parent, struct proc_dir_entry *proc)
240{
241 return 0;
242}
243//******************************************************************************
244//******************************************************************************
245int proc_unregister(struct proc_dir_entry *proc, int bla)
246{
247 return 0;
248}
249//******************************************************************************
250//******************************************************************************
251int fasync_helper(int a, struct file *b, int c, struct fasync_struct **d)
252{
253 return 0;
254}
255//******************************************************************************
256//******************************************************************************
257void kill_fasync(struct fasync_struct **a, int b, int c)
258{
259}
260//******************************************************************************
261//******************************************************************************
262int request_dma(unsigned int dmanr, const char * device_id) /* reserve a DMA channel */
263{
264 DebugInt3();
265 return 0;
266}
267//******************************************************************************
268//******************************************************************************
269void free_dma(unsigned int dmanr)
270{
271 DebugInt3();
272}
273//******************************************************************************
274/* enable/disable a specific DMA channel */
275//******************************************************************************
276void enable_dma(unsigned int dmanr)
277{
278 DebugInt3();
279}
280//******************************************************************************
281//******************************************************************************
282void disable_dma(unsigned int dmanr)
283{
284 DebugInt3();
285}
286//******************************************************************************
287//static struct notifier_block *reboot_notify_list = NULL;
288// No need to implement this right now. The ESS Maestro 3 driver uses it
289// to call pci_unregister_driver, which is always called from the shutdown
290// notification sent by OS2.
291// Same goes for es1968 & Yamaha's DS1/DS1E.
292//******************************************************************************
293int register_reboot_notifier(struct notifier_block *pnblock)
294{
295 return 0;
296}
297//******************************************************************************
298//******************************************************************************
299int unregister_reboot_notifier(struct notifier_block *pnblock)
300{
301 return 0;
302}
303//******************************************************************************
304//******************************************************************************
305static void __x_queue_work(struct workqueue_struct *wq, struct work_struct *work)
306{
307 unsigned long flags;
308
309 spin_lock_irqsave(&wq->lock, flags);
310 work->wq_data = wq;
311 list_add_tail(&work->entry, &wq->worklist);
312 wake_up(&wq->more_work);
313 spin_unlock_irqrestore(&wq->lock, flags);
314}
315//******************************************************************************
316//******************************************************************************
317int queue_work(struct workqueue_struct *wq, struct work_struct *work)
318{
319 if (!test_and_set_bit(0, &work->pending)) {
320 __x_queue_work(wq, work);
321 return 1;
322 }
323 return 0;
324}
325//******************************************************************************
326//******************************************************************************
327static void run_workqueue(struct workqueue_struct *wq)
328{
329 unsigned long flags;
330
331 spin_lock_irqsave(&wq->lock, flags);
332 while (!list_empty(&wq->worklist)) {
333 struct work_struct *work = list_entry(wq->worklist.next,
334 struct work_struct, entry);
335 void (*f) (void *) = work->func;
336 void *data = work->data;
337
338 list_del_init(wq->worklist.next);
339 spin_unlock_irqrestore(&wq->lock, flags);
340 clear_bit(0, &work->pending);
341 f(data);
342 spin_lock_irqsave(&wq->lock, flags);
343 wake_up(&wq->work_done);
344 }
345 spin_unlock_irqrestore(&wq->lock, flags);
346}
347//******************************************************************************
348//******************************************************************************
349void flush_workqueue(struct workqueue_struct *wq)
350{
351
352 if (wq->task == current) {
353 run_workqueue(wq);
354 } else {
355 struct wait_queue_entry wait;
356
357 init_waitqueue_entry(&wait, current);
358 set_current_state(TASK_UNINTERRUPTIBLE);
359 spin_lock_irq(&wq->lock);
360 add_wait_queue(&wq->work_done, &wait);
361#ifndef TARGET_OS2
362 while (!list_empty(&wq->worklist)) {
363 spin_unlock_irq(&wq->lock);
364 schedule(); // DAZ system hangs here because this function does nothing
365 spin_lock_irq(&wq->lock);
366 }
367#endif
368 set_current_state(TASK_RUNNING);
369 remove_wait_queue(&wq->work_done, &wait);
370 spin_unlock_irq(&wq->lock);
371 }
372}
373//******************************************************************************
374//******************************************************************************
375struct workqueue_struct *create_workqueue(const char *name)
376{
377 struct workqueue_struct *wq;
378
379 BUG_ON(strlen(name) > 10);
380
381 wq = kmalloc(sizeof(*wq), GFP_KERNEL);
382 if (!wq)
383 return NULL;
384 memset(wq, 0, sizeof(*wq));
385
386 spin_lock_init(&wq->lock);
387 INIT_LIST_HEAD(&wq->worklist);
388 init_waitqueue_head(&wq->more_work);
389 init_waitqueue_head(&wq->work_done);
390#ifndef TARGET_OS2
391 init_completion(&wq->thread_exited);
392 wq->name = name;
393 wq->task_pid = kernel_thread(xworker_thread, wq, 0);
394 if (wq->task_pid < 0) {
395 printk(KERN_ERR "snd: failed to start thread %s\n", name);
396 snd_compat_destroy_workqueue(wq);
397 wq = NULL;
398 }
399 wq->task = find_task_by_pid(wq->task_pid);
400#endif
401 return wq;
402}
403//******************************************************************************
404//******************************************************************************
405void destroy_workqueue(struct workqueue_struct *wq)
406{
407#ifndef TARGET_OS2
408 snd_compat_flush_workqueue(wq);
409 kill_proc(wq->task_pid, SIGKILL, 1);
410 if (wq->task_pid >= 0)
411 wait_for_completion(&wq->thread_exited);
412#endif
413 kfree(wq);
414}
415
416//******************************************************************************
417//******************************************************************************
418char *kstrdup(const char *s, unsigned int __nocast gfp_flags)
419{
420 int len;
421 char *buf;
422
423 if (!s) return NULL;
424
425 len = strlen(s) + 1;
426 buf = kmalloc(len, gfp_flags);
427 if (buf)
428 memcpy(buf, s, len);
429 return buf;
430}
431//******************************************************************************
432//******************************************************************************
433int mod_firmware_load(const char *fn, char **fp)
434{
435 return 0;
436}
437//******************************************************************************
438//******************************************************************************
439static int snd_try_load_firmware(const char *path, const char *name,
440 struct firmware *firmware)
441{
442 char filename[30 + FIRMWARE_NAME_MAX];
443
444 sprintf(filename, "%s/%s", path, name);
445 firmware->size = mod_firmware_load(filename, (char **)&firmware->data);
446 if (firmware->size)
447 printk(KERN_INFO "Loaded '%s'.", filename);
448 return firmware->size;
449}
450//******************************************************************************
451//******************************************************************************
452int request_firmware(const struct firmware **fw, const char *name,
453 struct device *device)
454{
455 struct firmware *firmware;
456
457 *fw = NULL;
458 firmware = kmalloc(sizeof *firmware, GFP_KERNEL);
459 if (!firmware)
460 return -ENOMEM;
461 if (!snd_try_load_firmware("/lib/firmware", name, firmware) &&
462 !snd_try_load_firmware("/lib/hotplug/firmware", name, firmware) &&
463 !snd_try_load_firmware("/usr/lib/hotplug/firmware", name, firmware)) {
464 kfree(firmware);
465 return -EIO;
466 }
467 *fw = firmware;
468 return 0;
469}
470//******************************************************************************
471//******************************************************************************
472void release_firmware(const struct firmware *fw)
473{
474 if (fw) {
475 vfree(fw->data);
476 kfree(fw);
477 }
478}
479//******************************************************************************
480//******************************************************************************
481void *memdup_user(const void __user *src, size_t len)
482{
483 void *p = kmalloc(len, GFP_KERNEL);
484 if (!p)
485 return ERR_PTR(-ENOMEM);
486 if (copy_from_user(p, src, len)) {
487 kfree(p);
488 return ERR_PTR(-EFAULT);
489 }
490 return p;
491}
492//******************************************************************************
493//******************************************************************************
494#define del_timer_sync(t) del_timer(t) /* FIXME: not quite correct on SMP */
495int cancel_delayed_work(struct delayed_work *dwork)
496{
497 struct work_struct *work = &dwork->work;
498 int ret;
499
500 ret = del_timer_sync(&work->timer);
501 if (ret)
502 clear_bit(0, &work->pending);
503 return ret;
504}
505//******************************************************************************
506//******************************************************************************
507struct workqueue_struct *system_wq;
508
509int schedule_work(struct work_struct *work)
510{
511#ifndef TARGET_OS2 // crashes
512 return queue_work(system_wq, work);
513#endif
514 return 0;
515}
516
517//******************************************************************************
518//******************************************************************************
519bool flush_delayed_work_sync(struct delayed_work *dwork)
520{
521 bool ret;
522 ret = cancel_delayed_work(dwork);
523 if (ret) {
524 schedule_delayed_work(dwork, 0);
525 flush_scheduled_work();
526 }
527 return ret;
528}
529//******************************************************************************
530//******************************************************************************
531static void delayed_work_timer_fn(unsigned long __data)
532{
533 struct work_struct *work = (struct work_struct *)__data;
534 struct workqueue_struct *wq = work->wq_data;
535
536 if (wq)
537 __x_queue_work(wq, work);
538 else
539 schedule_work(work);
540}
541//******************************************************************************
542//******************************************************************************
543int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay)
544{
545 struct work_struct *work = &dwork->work;
546 struct timer_list *timer = &work->timer;
547
548 if (!test_and_set_bit(0, &work->pending)) {
549 work->wq_data = wq;
550 timer->expires = jiffies + delay;
551 timer->data = (unsigned long)work;
552 timer->function = delayed_work_timer_fn;
553 add_timer(timer);
554 return 1;
555 }
556 return 0;
557}
558//******************************************************************************
559//******************************************************************************
560/* Greatest common divisor */
561unsigned long gcd(unsigned long a, unsigned long b)
562{
563 unsigned long r;
564 if (a < b) {
565 r = a;
566 a = b;
567 b = r;
568 }
569 while ((r = a % b) != 0) {
570 a = b;
571 b = r;
572 }
573 return b;
574}
575
576//******************************************************************************
577//******************************************************************************
578int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
579{
580 char *tail;
581 unsigned long val;
582 size_t len;
583
584 *res = 0;
585 len = strlen(cp);
586 if (len == 0)
587 return -EINVAL;
588
589 val = simple_strtoul(cp, &tail, base);
590 if (tail == cp)
591 return -EINVAL;
592
593 if ((*tail == '\0') ||
594 ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) {
595 *res = val;
596 return 0;
597 }
598
599 return -EINVAL;
600}
601//******************************************************************************
602//******************************************************************************
603
604static void u32_swap(void *a, void *b, int size)
605{
606 u32 t = *(u32 *)a;
607 *(u32 *)a = *(u32 *)b;
608 *(u32 *)b = t;
609}
610
611static void generic_swap(void *a, void *b, int size)
612{
613 char t;
614
615 do {
616 t = *(char *)a;
617 *(char *)a++ = *(char *)b;
618 *(char *)b++ = t;
619 } while (--size > 0);
620}
621
622/**
623 * sort - sort an array of elements
624 * @base: pointer to data to sort
625 * @num: number of elements
626 * @size: size of each element
627 * @cmp_func: pointer to comparison function
628 * @swap_func: pointer to swap function or NULL
629 *
630 * This function does a heapsort on the given array. You may provide a
631 * swap_func function optimized to your element type.
632 *
633 * Sorting time is O(n log n) both on average and worst-case. While
634 * qsort is about 20% faster on average, it suffers from exploitable
635 * O(n*n) worst-case behavior and extra memory requirements that make
636 * it less suitable for kernel use.
637 */
638
639void sort(void *base, size_t num, size_t size,
640 int (*cmp_func)(const void *, const void *),
641 void (*swap_func)(void *, void *, int size))
642{
643 /* pre-scale counters for performance */
644 int i = (num/2 - 1) * size, n = num * size, c, r;
645
646 if (!swap_func)
647 swap_func = (size == 4 ? u32_swap : generic_swap);
648
649 /* heapify */
650 for ( ; i >= 0; i -= size) {
651 for (r = i; r * 2 + size < n; r = c) {
652 c = r * 2 + size;
653 if (c < n - size &&
654 cmp_func(base + c, base + c + size) < 0)
655 c += size;
656 if (cmp_func(base + r, base + c) >= 0)
657 break;
658 swap_func(base + r, base + c, size);
659 }
660 }
661
662 /* sort */
663 for (i = n - size; i > 0; i -= size) {
664 swap_func(base, base + i, size);
665 for (r = 0; r * 2 + size < i; r = c) {
666 c = r * 2 + size;
667 if (c < i - size &&
668 cmp_func(base + c, base + c + size) < 0)
669 c += size;
670 if (cmp_func(base + r, base + c) >= 0)
671 break;
672 swap_func(base + r, base + c, size);
673 }
674 }
675}
676//******************************************************************************
677//******************************************************************************
678
679/**
680 * hex_to_bin - convert a hex digit to its real value
681 * @ch: ascii character represents hex digit
682 *
683 * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
684 * input.
685 */
686int hex_to_bin(char ch)
687{
688 if ((ch >= '0') && (ch <= '9'))
689 return ch - '0';
690 ch = tolower(ch);
691 if ((ch >= 'a') && (ch <= 'f'))
692 return ch - 'a' + 10;
693 return -1;
694}
695//******************************************************************************
696
697
698/*
699 * stream_open is used by subsystems that want stream-like file descriptors.
700 * Such file descriptors are not seekable and don't have notion of position
701 * (file.f_pos is always 0). Contrary to file descriptors of other regular
702 * files, .read() and .write() can run simultaneously.
703 *
704 * stream_open never fails and is marked to return int so that it could be
705 * directly used as file_operations.open .
706 */
707int stream_open(struct inode *inode, struct file *filp)
708{
709 filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS);
710 filp->f_mode |= FMODE_STREAM;
711 return 0;
712}
713
714/**
715 * alloc_pages_exact - allocate pages with the given size
716 * @size: the size to allocate in bytes
717 * @gfp_flags: the allocation conditions, GFP_XXX
718 *
719 * Allocates the physically contiguous pages with the given size.
720 *
721 * Return: The pointer of the buffer, or %NULL if no enough memory.
722 */
723void *alloc_pages_exact(size_t size, gfp_t gfp_flags)
724{
725 int pg;
726
727 if (WARN_ON(!size))
728 return NULL;
729 if (WARN_ON(!gfp_flags))
730 return NULL;
731 gfp_flags |= __GFP_COMP; /* compound page lets parts be mapped */
732 pg = get_order(size);
733 return (void *) __get_free_pages(gfp_flags, pg);
734}
735
736/**
737 * free_pages_exact - release the pages
738 * @ptr: the buffer pointer to release
739 * @size: the allocated buffer size
740 *
741 * Releases the buffer allocated via snd_malloc_pages().
742 */
743void free_pages_exact(void *ptr, size_t size)
744{
745 int pg;
746
747 if (ptr == NULL)
748 return;
749 pg = get_order(size);
750 free_pages((unsigned long) ptr, pg);
751}
Note: See TracBrowser for help on using the repository browser.