]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/taskwatch.c
OMAP: DSP: N800: remaining updates for dsp parts
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / taskwatch.c
1 /*
2  * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1)
3  *
4  * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved.
5  *
6  * Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/module.h>
25 #include <linux/fs.h>
26 #include <linux/poll.h>
27 #include <linux/sched.h>
28 #include <asm/uaccess.h>
29 #include <asm/arch/dsp.h>
30 #include "dsp_mbcmd.h"
31 #include "dsp.h"
32
33 static DECLARE_WAIT_QUEUE_HEAD(read_wait_q);
34 static unsigned int change_cnt;
35
36 void dsp_twch_touch(void)
37 {
38         change_cnt++;
39         wake_up_interruptible(&read_wait_q);
40 }
41
42 /*
43  * @count: represents the device counts of the user's interst
44  */
45 static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count,
46                              loff_t *ppos)
47 {
48         long taskstat[TASKDEV_MAX];
49         int devcount = count / sizeof(long);
50         int i;
51         DEFINE_WAIT(wait);
52
53         if (dsp_cfgstat_get_stat() != CFGSTAT_READY) {
54                 printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
55                 return -EINVAL;
56         }
57
58         prepare_to_wait(&read_wait_q, &wait, TASK_INTERRUPTIBLE);
59         if (change_cnt == 0)    /* last check */
60                 schedule();
61         finish_wait(&read_wait_q, &wait);
62
63         /* unconfigured while waiting ;-( */
64         if ((change_cnt == 0) && (dsp_cfgstat_get_stat() != CFGSTAT_READY))
65                 return -EINVAL;
66
67         if (devcount > TASKDEV_MAX)
68                 devcount = TASKDEV_MAX;
69
70         count = devcount * sizeof(long);
71         change_cnt = 0;
72         for (i = 0; i < devcount; i++) {
73                 /*
74                  * once the device state is read, the 'STALE' bit will be set
75                  * so that the Dynamic Loader can distinguish the new request
76                  * from the old one.
77                  */
78                 taskstat[i] = taskdev_state_stale(i);
79         }
80
81         if (copy_to_user(buf, taskstat, count))
82                 return -EFAULT;
83
84         return count;
85 }
86
87 static unsigned int dsp_twch_poll(struct file *file, poll_table *wait)
88 {
89         unsigned int mask = 0;
90
91         poll_wait(file, &read_wait_q, wait);
92         if (change_cnt)
93                 mask |= POLLIN | POLLRDNORM;
94
95         return mask;
96 }
97
98 static int dsp_twch_ioctl(struct inode *inode, struct file *file,
99                           unsigned int cmd, unsigned long arg)
100 {
101         int ret;
102
103         switch (cmd) {
104         case TWCH_IOCTL_MKDEV:
105                 {
106                         char name[TNM_LEN];
107                         if (copy_from_user(name, (void __user *)arg, TNM_LEN))
108                                 return -EFAULT;
109                         name[TNM_LEN-1] = '\0';
110                         ret = dsp_mkdev(name);
111                         break;
112                 }
113
114         case TWCH_IOCTL_RMDEV:
115                 {
116                         char name[TNM_LEN];
117                         if (copy_from_user(name, (void __user *)arg, TNM_LEN))
118                                 return -EFAULT;
119                         name[TNM_LEN-1] = '\0';
120                         ret = dsp_rmdev(name);
121                         break;
122                 }
123
124         case TWCH_IOCTL_TADD:
125                 {
126                         struct omap_dsp_taddinfo ti;
127                         if (copy_from_user(&ti, (void __user *)arg, sizeof(ti)))
128                                 return -EFAULT;
129                         ret = dsp_tadd_minor(ti.minor, ti.taskadr);
130                         break;
131                 }
132
133         case TWCH_IOCTL_TDEL:
134                 ret = dsp_tdel_minor(arg);
135                 break;
136
137         case TWCH_IOCTL_TKILL:
138                 ret = dsp_tkill_minor(arg);
139                 break;
140
141         default:
142                 return -ENOIOCTLCMD;
143         }
144
145         return ret;
146 }
147
148 struct file_operations dsp_twch_fops = {
149         .owner = THIS_MODULE,
150         .read  = dsp_twch_read,
151         .poll  = dsp_twch_poll,
152         .ioctl = dsp_twch_ioctl,
153 };
154
155 void dsp_twch_start(void)
156 {
157         change_cnt = 1;         /* first read will not wait */
158 }
159
160 void dsp_twch_stop(void)
161 {
162         wake_up_interruptible(&read_wait_q);
163 }