"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "usr/lib/oss/build/osscore.c" of archive oss-linux-v4.0-1016-x86_64.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  * Purpose: Linux kernel version specific wrapper routines.
    3  *
    4  * This file will be shipped in source format and compiled in the target
    5  * (customer) system. In this way minor changes between Linux versions
    6  * can be fixed by the customer.
    7  */
    8 
    9 /*
   10  * Copyright (C) 4Front Technologies 2005-2007. Released under GPL2 license.
   11  */
   12 //#include <linux/config.h>
   13 typedef int *ioctl_arg;
   14 #include <linux/init.h>
   15 #include <linux/module.h>
   16 #include <linux/delay.h>
   17 #include <stdarg.h>
   18 #include <linux/vmalloc.h>
   19 #include "../include/internals/timestamp.h"
   20 #include "ossddk/oss_exports.h"
   21 #include "wrap.h"
   22 #include "ossdip.h"
   23 #include <linux/version.h>
   24 #include <linux/fs.h>
   25 #include <linux/poll.h>
   26 #include <linux/time.h>
   27 #include <linux/proc_fs.h>
   28 #include <linux/spinlock.h>
   29 #include <linux/pci.h>
   30 #include <linux/irq.h>
   31 #include <linux/interrupt.h>
   32 #undef strlen
   33 #undef strcpy
   34 #define strlen oss_strlen
   35 #define strcpy oss_strcpy
   36 
   37 typedef struct _smap_t dmap_t;
   38 
   39 #include "../include/sys/soundcard.h"
   40 #include "../include/internals/audio_core.h"
   41 #include "../include/internals/mixer_core.h"
   42 
   43 extern int flat_device_model;
   44 
   45 MODULE_LICENSE ("GPL v2");
   46 MODULE_DESCRIPTION ("Open Sound System core services");
   47 MODULE_AUTHOR ("4Front Technologies (support@opensound.com)");
   48 
   49 struct _oss_mutex_t
   50 {
   51   /* Caution! This definition must match cuckoo.h */
   52   spinlock_t lock;
   53   int filler;			/* Make sure this structure doesn't become zero length */
   54 };
   55 
   56 static oss_device_t *core_osdev = NULL;
   57 /*
   58  * Minor device list
   59  */
   60 #define MAX_MINOR 256
   61 typedef struct
   62 {
   63   int major, minor;
   64   char name[32];
   65 } oss_minor_t;
   66 
   67 static oss_minor_t minors[MAX_MINOR];
   68 static int nminors = 0;
   69 
   70 /*
   71  * Sleep flags. Make sure these definitions match oss_config.h.
   72  */
   73 #define WK_NONE		0x00
   74 #define WK_WAKEUP	0x01
   75 #define WK_TIMEOUT	0x02
   76 #define WK_SIGNAL	0x04
   77 #define WK_SLEEP	0x08
   78 #define WK_SELECT	0x10
   79 
   80 time_t
   81 oss_get_time (void)
   82 {
   83 #if 1
   84   return get_seconds ();
   85 #else
   86   return xtime.tv_sec;
   87 #endif
   88 }
   89 
   90 void *oss_memset (void *t, int val, size_t l);
   91 
   92 void *
   93 oss_kmem_alloc (size_t size)
   94 {
   95   void *ptr;
   96   if ((ptr = vmalloc (size)) == NULL)
   97     {
   98       oss_cmn_err (CE_WARN, "vmalloc(%d) failed\n", size);
   99       return NULL;
  100     }
  101   memset (ptr, 0, size);
  102   return ptr;
  103 }
  104 
  105 void
  106 oss_kmem_free (void *addr)
  107 {
  108   vfree (addr);
  109 }
  110 
  111 #define MAX_MEMBLOCK	4096
  112 static void *memblocks[MAX_MEMBLOCK];
  113 static int n_memblocks = 0;
  114 
  115 void *
  116 oss_pmalloc (size_t sz)
  117 {
  118   void *ptr;
  119 
  120   if ((ptr = vmalloc (sz)) == NULL)
  121     {
  122       oss_cmn_err (CE_WARN, "vmalloc(%d) failed (PMALLOC)\n", sz);
  123       return NULL;
  124     }
  125   memset (ptr, 0, sz);
  126 
  127   if (n_memblocks <= MAX_MEMBLOCK)
  128     memblocks[n_memblocks++] = ptr;
  129 
  130   return ptr;
  131 }
  132 
  133 extern oss_native_word
  134 oss_virt_to_bus (void *addr)
  135 {
  136   return virt_to_bus (addr);
  137 }
  138 
  139 void *
  140 oss_memcpy (void *t_, const void *f_, size_t l)
  141 {
  142   unsigned char *t = t_;
  143   unsigned const char *f = f_;
  144   int i;
  145 
  146   for (i = 0; i < l; i++)
  147     *t++ = *f++;
  148 
  149   return t;
  150 }
  151 
  152 void *
  153 oss_memset (void *t, int val, size_t l)
  154 {
  155   char *c = t;
  156   while (l-- > 0)
  157     *c++ = val;
  158 
  159   return t;
  160 }
  161 
  162 int
  163 oss_strcmp (const char *s1, const char *s2)
  164 {
  165   while (*s1 && *s2)
  166     {
  167       if (*s1 != *s2)
  168 	return *s1 - *s2;
  169       s1++;
  170       s2++;
  171     }
  172 
  173   return *s1 - *s2;
  174 }
  175 
  176 int
  177 oss_strncmp (const char *s1, const char *s2, size_t len)
  178 {
  179   while (*s1 && *s2 && len--)
  180     {
  181       if (*s1 != *s2)
  182 	return *s1 - *s2;
  183       s1++;
  184       s2++;
  185     }
  186 
  187   return *s1 - *s2;
  188 }
  189 
  190 char *
  191 oss_strcpy (char *s1, const char *s2)
  192 {
  193   char *s = s1;
  194 
  195   while (*s2)
  196     *s1++ = *s2++;
  197   *s1++ = 0;
  198   return s;
  199 }
  200 
  201 size_t
  202 oss_strlen (const char *s)
  203 {
  204   int i;
  205 
  206   for (i = 0; s[i]; i++);
  207 
  208   return i;
  209 }
  210 
  211 char *
  212 oss_strncpy (char *s1, const char *s2, size_t l)
  213 {
  214   char *s = s1;
  215   int n = 0;
  216 
  217   while (*s2)
  218     {
  219       if (n++ >= l)
  220 	return s;
  221 
  222       *s1++ = *s2++;
  223     }
  224   *s1++ = 0;
  225   return s;
  226 }
  227 
  228 int oss_hz = HZ;
  229 extern int max_intrate;
  230 extern int detect_trace;
  231 extern int src_quality;
  232 
  233 module_param (oss_hz, int, S_IRUGO);
  234 module_param (max_intrate, int, S_IRUGO);
  235 module_param (detect_trace, int, S_IRUGO);
  236 module_param (src_quality, int, S_IRUGO);
  237 
  238 static struct proc_dir_entry *oss_proc_root = NULL;
  239 static struct proc_dir_entry *oss_proc_devfiles = NULL;
  240 
  241 static ssize_t
  242 oss_read_devfiles (struct file *file, char __user * buf, size_t count,
  243 		   loff_t * ppos)
  244 {
  245   static char tmp[4096];
  246   char *s;
  247   static int eof = 0;
  248   int i;
  249 
  250   if (eof)
  251     {
  252       eof = 0;
  253       return 0;
  254     }
  255 
  256   *tmp = 0;
  257   s = tmp;
  258 
  259   for (i = 0; i < nminors; i++)
  260     {
  261       if (strlen (tmp) > sizeof (tmp) - 20)
  262 	{
  263 	  printk (KERN_ALERT "osscore: Procfs buffer too small\n");
  264 	  return -ENOMEM;
  265 	}
  266 
  267       s += sprintf (s, "%s %d %d\n",
  268 		    minors[i].name, minors[i].major, minors[i].minor);
  269     }
  270 
  271   if (copy_to_user (buf, (void *) tmp, strlen (tmp)))
  272     return -EFAULT;
  273 
  274   eof = 1;
  275   return strlen (tmp);
  276 }
  277 
  278 static struct file_operations oss_proc_operations = {
  279   .read = oss_read_devfiles,
  280 };
  281 
  282 static void
  283 init_proc_fs (void)
  284 {
  285   if ((oss_proc_root =
  286        create_proc_entry ("opensound", 0700 | S_IFDIR, &proc_root)) == NULL)
  287     {
  288       oss_cmn_err (CE_CONT, "Cannot create /proc/opensound\n");
  289       return;
  290     }
  291 
  292   if ((oss_proc_devfiles =
  293        create_proc_entry ("devfiles", 0600, oss_proc_root)) == NULL)
  294     {
  295       oss_cmn_err (CE_CONT, "Cannot create /proc/opensound/devfiles\n");
  296       return;
  297     }
  298 
  299   oss_proc_devfiles->proc_fops = &oss_proc_operations;
  300 }
  301 
  302 static void
  303 uninit_proc_fs (void)
  304 {
  305   if (oss_proc_root)
  306     {
  307       if (oss_proc_devfiles)
  308 	remove_proc_entry ("devfiles", oss_proc_root);
  309       remove_proc_entry ("opensound", &proc_root);
  310     }
  311 }
  312 
  313 static int
  314 osscore_init (void)
  315 {
  316   if ((core_osdev =
  317        osdev_create (NULL, DRV_UNKNOWN, 0, "osscore", NULL)) == NULL)
  318     {
  319       oss_cmn_err (CE_WARN, "Failed to allocate OSDEV structure\n");
  320       return -ENOMEM;
  321     }
  322 
  323   osdev_set_owner (core_osdev, THIS_MODULE);
  324 
  325   init_proc_fs ();
  326 
  327   return oss_init_osscore (core_osdev);
  328 }
  329 
  330 static void
  331 osscore_exit (void)
  332 {
  333   int i;
  334 
  335   uninit_proc_fs ();
  336   oss_uninit_osscore (core_osdev);
  337 
  338   for (i = 0; i < n_memblocks; i++)
  339     if (memblocks[i] != NULL)
  340       {
  341 	vfree (memblocks[i]);
  342 	memblocks[i] = NULL;
  343       }
  344 }
  345 
  346 void
  347 oss_udelay (unsigned long d)
  348 {
  349   udelay (d);
  350 }
  351 
  352 oss_mutex_t
  353 oss_mutex_init (void)
  354 {
  355   oss_mutex_t mutex;
  356 
  357   if ((mutex = vmalloc (sizeof (*mutex))) == NULL)
  358     {
  359       oss_cmn_err (CE_WARN, "vmalloc(%d) failed (mutex)\n", sizeof (*mutex));
  360       return NULL;
  361     }
  362 
  363   spin_lock_init (&(mutex->lock));
  364 
  365   return mutex;
  366 }
  367 
  368 void
  369 oss_mutex_cleanup (oss_mutex_t mutex)
  370 {
  371   vfree (mutex);
  372 }
  373 
  374 void
  375 oss_spin_lock_irqsave (oss_mutex_t mutex, oss_native_word * flags)
  376 {
  377   unsigned long flag;
  378   if (mutex == NULL)
  379     return;
  380   spin_lock_irqsave (&mutex->lock, flag);
  381   *flags = flag;
  382 }
  383 
  384 void
  385 oss_spin_unlock_irqrestore (oss_mutex_t mutex, oss_native_word flags)
  386 {
  387   if (mutex == NULL)
  388     return;
  389   spin_unlock_irqrestore (&mutex->lock, flags);
  390 }
  391 
  392 void
  393 oss_spin_lock (oss_mutex_t mutex)
  394 {
  395   if (mutex == NULL)
  396     return;
  397   spin_lock (&mutex->lock);
  398 }
  399 
  400 void
  401 oss_spin_unlock (oss_mutex_t mutex)
  402 {
  403   if (mutex == NULL)
  404     return;
  405   spin_unlock (&mutex->lock);
  406 }
  407 
  408 void *
  409 oss_map_pci_mem (oss_device_t * osdev, int size, unsigned long offset)
  410 {
  411   return ioremap (offset, size);
  412 }
  413 
  414 void
  415 oss_unmap_pci_mem (void *addr)
  416 {
  417   iounmap (addr);
  418 }
  419 
  420 unsigned long long
  421 oss_get_jiffies (void)
  422 {
  423   return jiffies_64;
  424 }
  425 
  426 char *
  427 oss_get_procname (void)
  428 {
  429   return current->comm;
  430 }
  431 
  432 int
  433 oss_get_pid (void)
  434 {
  435   return current->pid;
  436 }
  437 
  438 int
  439 oss_get_uid (void)
  440 {
  441   return current->uid;
  442 }
  443 
  444 typedef struct tmout_desc
  445 {
  446   volatile int active;
  447   int timestamp;
  448   void (*func) (void *);
  449   void *arg;
  450 
  451   struct timer_list timer;
  452 } tmout_desc_t;
  453 
  454 static volatile int next_id = 0;
  455 #define MAX_TMOUTS 128
  456 
  457 tmout_desc_t tmouts[MAX_TMOUTS] = { {0} };
  458 
  459 int timeout_random = 0x12123400;
  460 
  461 void
  462 oss_timer_callback (unsigned long id)
  463 {
  464   tmout_desc_t *tmout;
  465   int ix;
  466   void *arg;
  467 
  468   timeout_random++;
  469 
  470   ix = id & 0xff;
  471   if (ix < 0 || ix >= MAX_TMOUTS)
  472     return;
  473   tmout = &tmouts[ix];
  474 
  475   if (tmout->timestamp != id)	/* Expired timer */
  476     return;
  477 
  478   if (!tmout->active)
  479     return;
  480 
  481   arg = tmout->arg;
  482   tmout->active = 0;
  483   tmout->timestamp = 0;
  484 
  485   tmout->func (arg);
  486 }
  487 
  488 timeout_id_t
  489 oss_timeout (void (*func) (void *), void *arg, unsigned long long ticks)
  490 {
  491   tmout_desc_t *tmout = NULL;
  492   int id, n;
  493 
  494   timeout_random++;
  495 
  496   n = 0;
  497   id = -1;
  498 
  499   while (id == -1 && n < MAX_TMOUTS)
  500     {
  501       if (!tmouts[next_id].active)
  502 	{
  503 	  tmouts[next_id].active = 1;
  504 	  id = next_id++;
  505 	  tmout = &tmouts[id];
  506 	  break;
  507 	}
  508 
  509       next_id = (next_id + 1) % MAX_TMOUTS;
  510     }
  511 
  512   if (id == -1)			/* No timer slots available */
  513     {
  514       oss_cmn_err (CE_WARN, "Timeout table full\n");
  515       return 0;
  516     }
  517 
  518   tmout->func = func;
  519   tmout->arg = arg;
  520   tmout->timestamp = id | (timeout_random & ~0xff);
  521 
  522   init_timer (&tmout->timer);
  523   tmout->timer.expires = jiffies + ticks;
  524   tmout->timer.data = id | (timeout_random & ~0xff);
  525   tmout->timer.function = oss_timer_callback;
  526   add_timer (&tmout->timer);
  527 
  528   return id | (timeout_random & ~0xff);
  529 }
  530 
  531 void
  532 oss_untimeout (timeout_id_t id)
  533 {
  534   tmout_desc_t *tmout;
  535   int ix;
  536 
  537   ix = id & 0xff;
  538   if (ix < 0 || ix >= MAX_TMOUTS)
  539     return;
  540 
  541   timeout_random++;
  542   tmout = &tmouts[ix];
  543 
  544   if (tmout->timestamp != id)	/* Expired timer */
  545     return;
  546   if (tmout->active)
  547     del_timer (&tmout->timer);
  548   tmout->active = 0;
  549   tmout->timestamp = 0;
  550 }
  551 
  552 int
  553 oss_uiomove (void *addr, size_t nbytes, enum uio_rw rwflag, uio_t * uio)
  554 {
  555 /*
  556  * NOTE! Returns 0 upon success and EFAULT on failure (instead of -EFAULT
  557  * (for Solaris/BSD compatibilityi)).
  558  */
  559 
  560   int c;
  561   char *address = addr;
  562 
  563   if (rwflag != uio->rw)
  564     {
  565       oss_cmn_err (CE_WARN, "uiomove: Bad direction\n");
  566       return EFAULT;
  567     }
  568 
  569   if (uio->resid < nbytes)
  570     {
  571       oss_cmn_err (CE_WARN, "uiomove: Bad count %d (%d)\n", nbytes,
  572 		   uio->resid);
  573       return EFAULT;
  574     }
  575 
  576   if (uio->kernel_space)
  577     return EFAULT;
  578 
  579   switch (rwflag)
  580     {
  581     case UIO_READ:
  582       c = nbytes;
  583       if (c > 10)
  584 	c = 0;
  585 
  586       if ((c = copy_to_user (uio->ptr, address, nbytes) != 0))
  587 	{
  588 	  uio->resid -= nbytes;
  589 	  oss_cmn_err (CE_CONT, "copy_to_user(%d) failed (%d)\n", nbytes, c);
  590 	  return EFAULT;
  591 	}
  592       break;
  593 
  594     case UIO_WRITE:
  595       if (copy_from_user (address, uio->ptr, nbytes) != 0)
  596 	{
  597 	  oss_cmn_err (CE_CONT, "copy_from_user failed\n");
  598 	  uio->resid -= nbytes;
  599 	  return EFAULT;
  600 	}
  601       break;
  602     }
  603 
  604   uio->resid -= nbytes;
  605   uio->ptr += nbytes;
  606 
  607   return 0;
  608 }
  609 
  610 int
  611 oss_create_uio (uio_t * uio, char *buf, size_t count, uio_rw_t rw,
  612 		int is_kernel)
  613 {
  614   memset (uio, 0, sizeof (*uio));
  615 
  616   if (is_kernel)
  617     {
  618       oss_cmn_err (CE_CONT,
  619 		   "oss_create_uio: Kernel space buffers not supported\n");
  620       return -EIO;
  621     }
  622 
  623   uio->ptr = buf;
  624   uio->resid = count;
  625   uio->kernel_space = is_kernel;
  626   uio->rw = rw;
  627 
  628   return 0;
  629 }
  630 
  631 void
  632 oss_cmn_err (int level, char *s, ...)
  633 {
  634   char tmp[1024], *a[6];
  635   va_list ap;
  636   int i, n = 0;
  637 
  638   va_start (ap, s);
  639 
  640   for (i = 0; i < strlen (s); i++)
  641     if (s[i] == '%')
  642       n++;
  643 
  644   for (i = 0; i < n && i < 6; i++)
  645     a[i] = va_arg (ap, char *);
  646 
  647   for (i = n; i < 6; i++)
  648     a[i] = NULL;
  649 
  650   if (level == CE_CONT)
  651     {
  652       sprintf (tmp, s, a[0], a[1], a[2], a[3], a[4], a[5], NULL,
  653 	       NULL, NULL, NULL);
  654       printk ("%s", tmp);
  655     }
  656   else
  657     {
  658       strcpy (tmp, "osscore: ");
  659       sprintf (tmp + strlen (tmp), s, a[0], a[1], a[2], a[3], a[4], a[5],
  660 	       NULL, NULL, NULL, NULL);
  661       if (level == CE_PANIC)
  662 	panic (tmp);
  663 
  664       printk (KERN_ALERT "%s", tmp);
  665     }
  666 #if 0
  667   /* This may cause a crash under SMP */
  668   if (sound_started)
  669     store_msg (tmp);
  670 #endif
  671 
  672   va_end (ap);
  673 }
  674 
  675 /*
  676  * Sleep/wakeup
  677  */
  678 
  679 struct oss_wait_queue
  680 {
  681   volatile int flags;
  682   wait_queue_head_t wq;
  683 };
  684 
  685 struct oss_wait_queue *
  686 oss_create_wait_queue (oss_device_t * osdev, const char *name)
  687 {
  688   struct oss_wait_queue *wq;
  689 
  690   if ((wq = vmalloc (sizeof (*wq))) == NULL)
  691     {
  692       oss_cmn_err (CE_WARN, "vmalloc(%d) failed (wq)\n", sizeof (*wq));
  693       return NULL;
  694     }
  695   init_waitqueue_head (&wq->wq);
  696 
  697   return wq;
  698 }
  699 
  700 void
  701 oss_reset_wait_queue (struct oss_wait_queue *wq)
  702 {
  703   wq->flags = 0;
  704 }
  705 
  706 void
  707 oss_remove_wait_queue (struct oss_wait_queue *wq)
  708 {
  709   vfree (wq);
  710 }
  711 
  712 int
  713 oss_sleep (struct oss_wait_queue *wq, oss_mutex_t * mutex, int ticks,
  714 	   oss_native_word * flags, unsigned int *status)
  715 {
  716   int result = 0;
  717   *status = 0;
  718 
  719   if (wq == NULL)
  720     return 0;
  721 
  722   wq->flags = 0;
  723   oss_spin_unlock_irqrestore (*mutex, *flags);
  724 
  725   if (ticks <= 0)
  726     result = wait_event_interruptible (wq->wq, (wq->flags & WK_WAKEUP));
  727   else
  728     result =
  729       wait_event_interruptible_timeout (wq->wq, (wq->flags & WK_WAKEUP),
  730 					ticks);
  731 
  732   oss_spin_lock_irqsave (*mutex, flags);
  733 
  734   if (result < 0)		/* Signal received */
  735     {
  736       *status |= WK_SIGNAL;
  737       return 1;
  738     }
  739 
  740   if (!(wq->flags & WK_WAKEUP))	/* Timeout */
  741     {
  742       return 0;
  743     }
  744 
  745   return 1;
  746 }
  747 
  748 int
  749 oss_register_poll (struct oss_wait_queue *wq, oss_mutex_t * mutex,
  750 		   oss_native_word * flags, oss_poll_event_t * ev)
  751 {
  752   oss_spin_unlock_irqrestore (*mutex, *flags);
  753   poll_wait ((struct file *) ev->file, &wq->wq,
  754 	     (struct poll_table_struct *) ev->wait);
  755   oss_spin_lock_irqsave (*mutex, flags);
  756   return 0;
  757 }
  758 
  759 void
  760 oss_wakeup (struct oss_wait_queue *wq, oss_mutex_t * mutex,
  761 	    oss_native_word * flags, short events)
  762 {
  763   if (wq == NULL)
  764     return;
  765 
  766   wq->flags |= WK_WAKEUP;
  767   oss_spin_unlock_irqrestore (*mutex, *flags);
  768   wake_up (&wq->wq);
  769   oss_spin_lock_irqsave (*mutex, flags);
  770 }
  771 
  772 void
  773 oss_reserve_pages (oss_native_word start_addr, oss_native_word end_addr)
  774 {
  775   struct page *page, *lastpage;
  776 
  777   lastpage = virt_to_page (end_addr);
  778 
  779   for (page = virt_to_page (start_addr); page <= lastpage; page++)
  780     set_bit (PG_reserved, &page->flags);
  781 }
  782 
  783 void
  784 oss_unreserve_pages (oss_native_word start_addr, oss_native_word end_addr)
  785 {
  786   struct page *page, *lastpage;
  787 
  788   lastpage = virt_to_page (end_addr);
  789 
  790   for (page = virt_to_page (start_addr); page <= lastpage; page++)
  791     clear_bit (PG_reserved, &page->flags);
  792 }
  793 
  794 void *
  795 oss_contig_malloc (oss_device_t * osdev, int buffsize, oss_uint64_t memlimit,
  796 		   oss_native_word * phaddr)
  797 {
  798   char *start_addr, *end_addr;
  799   int sz, size;
  800   int flags = 0;
  801 
  802   *phaddr = 0;
  803 
  804   if (memlimit <= 0x00000000ffffffffLL)
  805     flags |= GFP_DMA;
  806 
  807   start_addr = NULL;
  808 
  809   for (sz = 0, size = PAGE_SIZE; size < buffsize; sz++, size <<= 1);
  810 
  811   if (buffsize != (PAGE_SIZE * (1 << sz)))
  812     {
  813 #if 0
  814       printk
  815 	("Contig_malloc: Invalid size %d != %ld\n", buffsize,
  816 	 PAGE_SIZE * (1 << sz));
  817 #endif
  818     }
  819 
  820   start_addr = (char *) __get_free_pages (GFP_KERNEL | flags, sz);
  821 
  822   if (start_addr == NULL)
  823     {
  824       cmn_err (CE_NOTE, "Failed to allocate memory buffer of %d bytes\n",
  825 	       buffsize);
  826       return NULL;
  827     }
  828   else
  829     {
  830       /* make some checks */
  831       end_addr = start_addr + buffsize - 1;
  832 
  833       oss_reserve_pages ((oss_native_word) start_addr,
  834 			 (oss_native_word) end_addr);
  835     }
  836 
  837   *phaddr = virt_to_bus (start_addr);
  838   return start_addr;
  839 }
  840 
  841 void
  842 oss_contig_free (oss_device_t * osdev, void *p, int buffsize)
  843 {
  844   int sz, size;
  845   caddr_t start_addr, end_addr;
  846 
  847   if (p == NULL)
  848     return;
  849 
  850   for (sz = 0, size = PAGE_SIZE; size < buffsize; sz++, size <<= 1);
  851 
  852   start_addr = p;
  853   end_addr = p + buffsize - 1;
  854 
  855   oss_unreserve_pages ((oss_native_word) start_addr,
  856 		       (oss_native_word) end_addr);
  857   free_pages ((unsigned long) p, sz);
  858 }
  859 
  860 /*
  861  * These typedefs must match definition of struct file_operations.
  862  * (See notes in routine oss_register_chrdev).
  863  */
  864 typedef ssize_t (*read_t) (struct file *, char *, size_t, loff_t *);
  865 typedef ssize_t (*write_t) (struct file *, const char *, size_t, loff_t *);
  866 typedef unsigned int (*poll_t) (struct file *, poll_table *);
  867 typedef poll_table select_table;
  868 
  869 typedef int (*readdir_t) (struct inode *, struct file *, void *, filldir_t);
  870 typedef int (*ioctl_t) (struct inode *, struct file *, unsigned int,
  871 			unsigned long);
  872 typedef int (*mmap_t) (struct file *, struct vm_area_struct *);
  873 typedef int (*open_t) (struct inode *, struct file *);
  874 
  875 typedef int (*release_t) (struct inode *, struct file *);
  876 typedef int (*fasync_t) (int, struct file *, int);
  877 typedef int (*fsync_t) (struct inode *, struct file *);
  878 
  879 static loff_t
  880 oss_no_llseek (struct file *file, loff_t offset, int orig)
  881 {
  882   return -EINVAL;
  883 }
  884 
  885 static int
  886 oss_no_fsync (struct file *f, struct dentry *d, int datasync)
  887 {
  888   return -EINVAL;
  889 }
  890 
  891 static int
  892 oss_no_fasync (int x, struct file *f, int m)
  893 {
  894   return -EINVAL;
  895 }
  896 
  897 /*
  898  *	Wrappers for installing and uninstalling character and block devices.
  899  *
  900  *	The oss_file_operation_handle structure differs from kernel's
  901  *	file_operations structure in parameters of the driver entry points.
  902  *	Kernel inode, file, wait_struct, vm_are_struct etc. typed arguments
  903  *	are replaced by wrapper handles.
  904  */
  905 
  906 static struct file_operations *
  907 alloc_fop (oss_device_t * osdev, struct oss_file_operation_handle *op)
  908 {
  909 /*
  910  *	This routine performs initialization of kernel file_operations structure
  911  *	from oss_file_operation_handle structure. Each procedure pointer is copied
  912  *	to a temporary variable before doing the actual assignment. This
  913  *	prevents unnecessary warnings while it still enables compatibility
  914  *	warnings.
  915  *
  916  *	Any warning given by this routine may indicate that kernel fs
  917  *	call interface has changed significantly (added parameters to the routines).
  918  *	In this case definition routine in oss_file_operation_handle must be updated
  919  *	and WRAPPER_VERSION must be incremented.
  920  */
  921 
  922   struct file_operations *fop;
  923 
  924   poll_t tmp_poll = (poll_t) op->poll;
  925   read_t tmp_read = (read_t) op->read;
  926   write_t tmp_write = (write_t) op->write;
  927   /* readdir_t tmp_readdir = (readdir_t)op->readdir; */
  928   ioctl_t tmp_ioctl = (ioctl_t) op->ioctl;
  929   mmap_t tmp_mmap = (mmap_t) op->mmap;
  930   open_t tmp_open = (open_t) op->open;
  931   release_t tmp_release = (release_t) op->release;
  932 
  933   fop = (struct file_operations *)
  934     oss_kmem_alloc (sizeof (struct file_operations));
  935 
  936   memset ((char *) fop, 0, sizeof (struct file_operations));
  937 
  938 /*
  939  *	Now the assignment
  940  */
  941   fop->llseek = oss_no_llseek;
  942   fop->read = tmp_read;
  943   fop->write = tmp_write;
  944   fop->readdir = NULL;		/* tmp_readdir; */
  945   fop->poll = tmp_poll;
  946   fop->ioctl = tmp_ioctl;
  947   fop->mmap = tmp_mmap;
  948   fop->open = tmp_open;
  949   fop->release = tmp_release;
  950   fop->fsync = oss_no_fsync;
  951   fop->fasync = oss_no_fasync;
  952   fop->lock = NULL;
  953   fop->flush = NULL;
  954 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  955   fop->owner = osdev_get_owner (osdev);
  956 #endif
  957 
  958   return fop;
  959 }
  960 
  961 int
  962 oss_register_chrdev (oss_device_t * osdev, unsigned int major,
  963 		     const char *name, struct oss_file_operation_handle *op)
  964 {
  965   int maj;
  966   maj = register_chrdev (major, name, alloc_fop (osdev, op));
  967 
  968   return maj;
  969 }
  970 
  971 void
  972 oss_register_minor (int major, int minor, char *name)
  973 {
  974   if (nminors >= MAX_MINOR)
  975     {
  976       oss_cmn_err (CE_WARN, "Too many device files\n");
  977       return;
  978     }
  979 
  980   minors[nminors].major = major;
  981   minors[nminors].minor = minor;
  982   strcpy (minors[nminors].name, name);
  983   nminors++;
  984 }
  985 
  986 int
  987 oss_unregister_chrdev (unsigned int major, const char *name)
  988 {
  989   unregister_chrdev (major, name);
  990   return 0;
  991 }
  992 
  993 int
  994 oss_inode_get_minor (oss_inode_handle_t * inode)
  995 {
  996   return MINOR (((struct inode *) inode)->i_rdev);
  997 }
  998 
  999 int
 1000 oss_file_get_flags (oss_file_handle_t * file)
 1001 {
 1002   return ((struct file *) file)->f_flags;
 1003 }
 1004 
 1005 void *
 1006 oss_file_get_private (oss_file_handle_t * file)
 1007 {
 1008   return ((struct file *) file)->private_data;
 1009 }
 1010 
 1011 void
 1012 oss_file_set_private (oss_file_handle_t * file, void *v)
 1013 {
 1014   ((struct file *) file)->private_data = v;
 1015 }
 1016 
 1017 int
 1018 oss_vma_get_flags (oss_vm_area_handle_t * vma)
 1019 {
 1020   return ((struct vm_area_struct *) vma)->vm_flags;
 1021 }
 1022 
 1023 int
 1024 oss_do_mmap (oss_vm_area_handle_t * v, oss_native_word dmabuf_phys,
 1025 	     int bytes_in_use)
 1026 {
 1027   struct vm_area_struct *vma = (struct vm_area_struct *) v;
 1028   int res, size;
 1029 
 1030   if (vma->vm_pgoff != 0)
 1031     {
 1032       oss_cmn_err (CE_WARN, "mmap() offset must be 0.\n");
 1033       return -EINVAL;
 1034     }
 1035