]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/task.c
Merge with /home/tmlind/src/kernel/linux-2.6
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / task.c
1 /*
2  * linux/arch/arm/mach-omap/dsp/task.c
3  *
4  * OMAP DSP task device driver
5  *
6  * Copyright (C) 2002-2005 Nokia Corporation
7  *
8  * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
9  * mmap function by Hiroo Ishikawa <ext-hiroo.ishikawa@nokia.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  * 2005/07/26:  DSP Gateway version 3.3
26  */
27
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/major.h>
32 #include <linux/fs.h>
33 #include <linux/poll.h>
34 #include <linux/platform_device.h>
35 #include <linux/slab.h>
36 #include <linux/sched.h>
37 #include <linux/mm.h>
38 #include <linux/proc_fs.h>
39 #include <asm/uaccess.h>
40 #include <asm/io.h>
41 #include <asm/signal.h>
42 #include <asm/irq.h>
43 #include <asm/ioctls.h>
44 #include <asm/arch/dsp.h>
45 #include "uaccess_dsp.h"
46 #include "dsp.h"
47 #include "ipbuf.h"
48 #include "fifo.h"
49 #include "proclist.h"
50
51 #define is_aligned(adr,align)   (!((adr)&((align)-1)))
52
53 /*
54  * taskdev.state: device state machine
55  * NOTASK:      task is not attached.
56  * ATTACHED:    task is attached.
57  * GARBAGE:     task is detached. waiting for all processes to close this device.
58  * ADDREQ:      requesting for tadd
59  * DELREQ:      requesting for tdel. no process is opening this device.
60  * ADDFAIL:     tadd failed.
61  * ADDING:      tadd in process.
62  * DELING:      tdel in process.
63  * KILLING:     tkill in process.
64  */
65 #define devstate_name(stat) (\
66         ((stat) & OMAP_DSP_DEVSTATE_NOTASK)   ? "NOTASK" :\
67         ((stat) & OMAP_DSP_DEVSTATE_ATTACHED) ? "ATTACHED" :\
68         ((stat) & OMAP_DSP_DEVSTATE_GARBAGE)  ? "GARBAGE" :\
69         ((stat) & OMAP_DSP_DEVSTATE_INVALID)  ? "INVALID" :\
70         ((stat) & OMAP_DSP_DEVSTATE_ADDREQ)   ? "ADDREQ" :\
71         ((stat) & OMAP_DSP_DEVSTATE_DELREQ)   ? "DELREQ" :\
72         ((stat) & OMAP_DSP_DEVSTATE_ADDFAIL)  ? "ADDFAIL" :\
73         ((stat) & OMAP_DSP_DEVSTATE_ADDING)   ? "ADDING" :\
74         ((stat) & OMAP_DSP_DEVSTATE_DELING)   ? "DELING" :\
75         ((stat) & OMAP_DSP_DEVSTATE_KILLING)  ? "KILLING" :\
76                                                 "unknown")
77
78 struct taskdev {
79         struct bus_type *bus;
80 //      struct device_driver *driver;
81         struct device dev;      /* Generic device interface */
82
83         long state;
84         spinlock_t state_lock;
85         wait_queue_head_t state_wait_q;
86         unsigned int usecount;
87         char name[OMAP_DSP_TNM_LEN];
88         struct file_operations fops;
89         struct list_head proc_list;
90         struct dsptask *task;
91
92         /* read stuff */
93         wait_queue_head_t read_wait_q;
94         struct semaphore read_sem;
95
96         /* write stuff */
97         wait_queue_head_t write_wait_q;
98         struct semaphore write_sem;
99
100         /* ioctl stuff */
101         wait_queue_head_t ioctl_wait_q;
102         struct semaphore ioctl_sem;
103
104         /* device lock */
105         struct semaphore lock_sem;
106         pid_t lock_pid;
107 };
108
109 #define to_taskdev(n) container_of(n, struct taskdev, dev)
110
111 struct rcvdt_bk_struct {
112         struct ipblink link;
113         unsigned int rp;
114         struct ipbuf_p *ipbuf_pvt_r;
115 };
116
117 struct dsptask {
118         enum {
119                 TASK_STATE_ERR = 0,
120                 TASK_STATE_READY,
121                 TASK_STATE_CFGREQ
122         } state;
123         unsigned char tid;
124         char name[OMAP_DSP_TNM_LEN];
125         unsigned short ttyp;
126         struct taskdev *dev;
127
128         /* read stuff */
129         union {
130                 struct fifo_struct fifo;        /* for active word */
131                 struct rcvdt_bk_struct bk;
132         } rcvdt;
133
134         /* write stuff */
135         size_t wsz;
136         spinlock_t wsz_lock;
137         struct ipbuf_p *ipbuf_pvt_w;    /* for private block */
138
139         /* tctl stuff */
140         int tctl_stat;
141
142         /* mmap stuff */
143         void *map_base;
144         size_t map_length;
145 };
146
147 #define sndtyp_acv(ttyp)        ((ttyp) & OMAP_DSP_TTYP_ASND)
148 #define sndtyp_psv(ttyp)        (!((ttyp) & OMAP_DSP_TTYP_ASND))
149 #define sndtyp_bk(ttyp)         ((ttyp) & OMAP_DSP_TTYP_BKDM)
150 #define sndtyp_wd(ttyp)         (!((ttyp) & OMAP_DSP_TTYP_BKDM))
151 #define sndtyp_pvt(ttyp)        ((ttyp) & OMAP_DSP_TTYP_PVDM)
152 #define sndtyp_gbl(ttyp)        (!((ttyp) & OMAP_DSP_TTYP_PVDM))
153 #define rcvtyp_acv(ttyp)        ((ttyp) & OMAP_DSP_TTYP_ARCV)
154 #define rcvtyp_psv(ttyp)        (!((ttyp) & OMAP_DSP_TTYP_ARCV))
155 #define rcvtyp_bk(ttyp)         ((ttyp) & OMAP_DSP_TTYP_BKMD)
156 #define rcvtyp_wd(ttyp)         (!((ttyp) & OMAP_DSP_TTYP_BKMD))
157 #define rcvtyp_pvt(ttyp)        ((ttyp) & OMAP_DSP_TTYP_PVMD)
158 #define rcvtyp_gbl(ttyp)        (!((ttyp) & OMAP_DSP_TTYP_PVMD))
159
160 static int dsp_rmdev_minor(unsigned char minor);
161 static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor);
162 static void taskdev_delete(unsigned char minor);
163 static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task);
164 static void taskdev_detach_task(struct taskdev *dev);
165 static int dsp_tdel_bh(unsigned char minor, unsigned short type);
166
167 static ssize_t devname_show(struct device *d, struct device_attribute *attr,
168                             char *buf);
169 static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
170                              char *buf);
171 static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
172                               char *buf);
173 static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
174                              char *buf);
175 static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
176                          char *buf);
177 static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
178                            char *buf);
179 static int fifosz_store(struct device *d, struct device_attribute *attr,
180                         const char *buf, size_t count);
181 static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
182                             char *buf);
183 static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
184                             char *buf);
185 static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
186                         char *buf);
187 static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
188                          char *buf);
189
190 static struct device_attribute dev_attr_devname = __ATTR_RO(devname);
191 static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate);
192 static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list);
193 static struct device_attribute dev_attr_fifosz = 
194         __ATTR(fifosz, S_IWUGO | S_IRUGO, fifosz_show, fifosz_store);
195 static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt);
196 static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname);
197 static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp);
198 static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink);
199 static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz);
200 static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap);
201
202 static struct bus_type dsptask_bus = {
203         .name = "dsptask",
204 };
205
206 static struct class *dsp_task_class;
207 static struct taskdev *taskdev[TASKDEV_MAX];
208 static struct dsptask *dsptask[TASKDEV_MAX];
209 static DECLARE_MUTEX(cfg_sem);
210 static unsigned short cfg_cmd;
211 static unsigned char cfg_tid;
212 static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q);
213 static unsigned char n_task;
214 static void *heap;
215
216 #define devstate_lock(dev, devstate)    devstate_lock_timeout(dev, devstate, 0)
217
218 /*
219  * devstate_lock_timeout():
220  * when called with timeout > 0, dev->state can be diffeent from what you want.
221  */
222 static int devstate_lock_timeout(struct taskdev *dev, long devstate,
223                                  int timeout)
224 {
225         DECLARE_WAITQUEUE(wait, current);
226         long current_state = current->state;
227         int ret = 0;
228
229         spin_lock(&dev->state_lock);
230         add_wait_queue(&dev->state_wait_q, &wait);
231         while (!(dev->state & devstate)) {
232                 set_current_state(TASK_INTERRUPTIBLE);
233                 spin_unlock(&dev->state_lock);
234                 if (timeout) {
235                         if ((timeout = schedule_timeout(timeout)) == 0) {
236                                 /* timeout */
237                                 spin_lock(&dev->state_lock);
238                                 break;
239                         }
240                 }
241                 else
242                         schedule();
243                 if (signal_pending(current)) {
244                         ret = -ERESTARTSYS;
245                         break;
246                 }
247                 spin_lock(&dev->state_lock);
248         }
249         remove_wait_queue(&dev->state_wait_q, &wait);
250         set_current_state(current_state);
251         return ret;
252 }
253
254 static __inline__ void devstate_unlock(struct taskdev *dev)
255 {
256         spin_unlock(&dev->state_lock);
257 }
258
259 static __inline__ int down_tasksem_interruptible(struct taskdev *dev,
260                                                  struct semaphore *sem)
261 {
262         int ret;
263
264         if (dev->lock_pid == current->pid) {
265                 /* this process has lock */
266                 ret = down_interruptible(sem);
267         } else {
268                 if ((ret = down_interruptible(&dev->lock_sem)) != 0)
269                         return ret;
270                 ret = down_interruptible(sem);
271                 up(&dev->lock_sem);
272         }
273         return ret;
274 }
275
276 static void proclist_send_sigbus(struct list_head *list)
277 {
278         siginfo_t info;
279         struct proc_list *pl;
280         struct task_struct *tsk;
281
282         info.si_signo = SIGBUS;
283         info.si_errno = 0;
284         info.si_code = SI_KERNEL;
285         info._sifields._sigfault._addr = NULL;
286
287         /* need to lock tasklist_lock before calling find_task_by_pid_type. */
288         read_lock(&tasklist_lock);
289         list_for_each_entry(pl, list, list_head) {
290                 if ((tsk = find_task_by_pid_type(PIDTYPE_PID, pl->pid)) != NULL)
291                         send_sig_info(SIGBUS, &info, tsk);
292         }
293         read_unlock(&tasklist_lock);
294 }
295
296 static int dsp_task_flush_buf(struct dsptask *task)
297 {
298         unsigned short ttyp = task->ttyp;
299
300         if (sndtyp_wd(ttyp)) {
301                 /* word receiving */
302                 flush_fifo(&task->rcvdt.fifo);
303         } else {
304                 /* block receiving */
305                 struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
306
307                 spin_lock(&rcvdt->link.lock);
308                 if (sndtyp_gbl(ttyp)) {
309                         /* global IPBUF */
310                         while (!ipblink_empty(&rcvdt->link)) {
311                                 unsigned short bid = rcvdt->link.top;
312                                 ipblink_del_top(&rcvdt->link, ipbuf);
313                                 unuse_ipbuf(bid);
314                         }
315                 } else {
316                         /* private IPBUF */
317                         if (!ipblink_empty(&rcvdt->link)) {
318                                 ipblink_del_pvt(&rcvdt->link);
319                                 release_ipbuf_pvt(rcvdt->ipbuf_pvt_r);
320                         }
321                 }
322                 spin_unlock(&rcvdt->link.lock);
323         }
324
325         return 0;
326 }
327
328 static int dsp_task_set_fifosz(struct dsptask *task, unsigned long sz)
329 {
330         unsigned short ttyp = task->ttyp;
331         int stat;
332
333         if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) {
334                 printk(KERN_ERR
335                        "omapdsp: buffer size can be changed only for "
336                        "active word sending task.\n");
337                 return -EINVAL;
338         }
339         if ((sz == 0) || (sz & 1)) {
340                 printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n"
341                                 "it must be even and non-zero value.\n", sz);
342                 return -EINVAL;
343         }
344
345         stat = realloc_fifo(&task->rcvdt.fifo, sz);
346         if (stat == -EBUSY) {
347                 printk(KERN_ERR "omapdsp: buffer is not empty!\n");
348                 return stat;
349         } else if (stat < 0) {
350                 printk(KERN_ERR
351                        "omapdsp: unable to change receive buffer size. "
352                        "(%ld bytes for %s)\n", sz, task->name);
353                 return stat;
354         }
355
356         return 0;
357 }
358
359 static int taskdev_lock(struct taskdev *dev)
360 {
361         if (down_interruptible(&dev->lock_sem))
362                 return -ERESTARTSYS;
363         dev->lock_pid = current->pid;
364         return 0;
365 }
366
367 static int taskdev_unlock(struct taskdev *dev)
368 {
369         if (dev->lock_pid != current->pid) {
370                 printk(KERN_ERR
371                        "omapdsp: an illegal process attempted to "
372                        "unlock the dsptask lock!\n");
373                 return -EINVAL;
374         }
375         dev->lock_pid = 0;
376         up(&dev->lock_sem);
377         return 0;
378 }
379
380 static int dsp_task_config(struct dsptask *task, unsigned char tid)
381 {
382         unsigned short ttyp;
383         struct mbcmd mb;
384         int ret;
385
386         task->tid = tid;
387         dsptask[tid] = task;
388
389         /* TCFG request */
390         task->state = TASK_STATE_CFGREQ;
391         if (down_interruptible(&cfg_sem)) {
392                 ret = -ERESTARTSYS;
393                 goto fail_out;
394         }
395         cfg_cmd = MBCMD(TCFG);
396         mbcmd_set(mb, MBCMD(TCFG), tid, 0);
397         dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
398         cfg_cmd = 0;
399         up(&cfg_sem);
400
401         if (task->state != TASK_STATE_READY) {
402                 printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid);
403                 ret = -EINVAL;
404                 goto fail_out;
405         }
406
407         if (strlen(task->name) <= 1)
408                 sprintf(task->name, "%d", tid);
409         printk(KERN_INFO "omapdsp: task %d: name %s\n", tid, task->name);
410
411         ttyp = task->ttyp;
412
413         /*
414          * task info sanity check
415          */
416
417         /* task type check */
418         if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) {
419                 printk(KERN_ERR "omapdsp: illegal task type(0x%04x), tid=%d\n",
420                        tid, ttyp);
421                 ret = -EINVAL;
422                 goto fail_out;
423         }
424
425         /* private buffer address check */
426         if (sndtyp_pvt(ttyp) &&
427             (ipbuf_p_validate(task->rcvdt.bk.ipbuf_pvt_r, DIR_D2A) < 0)) {
428                 ret = -EINVAL;
429                 goto fail_out;
430         }
431         if (rcvtyp_pvt(ttyp) &&
432             (ipbuf_p_validate(task->ipbuf_pvt_w, DIR_A2D) < 0)) {
433                 ret = -EINVAL;
434                 goto fail_out;
435         }
436         
437         /* mmap buffer configuration check */
438         if ((task->map_length > 0) &&
439             ((!is_aligned((unsigned long)task->map_base, PAGE_SIZE)) ||
440              (!is_aligned(task->map_length, PAGE_SIZE)) ||
441              (dsp_mem_type(task->map_base, task->map_length) != MEM_TYPE_EXTERN))) {
442                 printk(KERN_ERR
443                        "omapdsp: illegal mmap buffer address(0x%p) or "
444                        "length(0x%x).\n"
445                        "  It needs to be page-aligned and located at "
446                        "external memory.\n",
447                        task->map_base, task->map_length);
448                 ret = -EINVAL;
449                 goto fail_out;
450         }
451
452         /*
453          * initialization
454          */
455
456         /* read initialization */
457         if (sndtyp_wd(ttyp)) {
458                 /* word */
459                 size_t fifosz;
460
461                 fifosz = sndtyp_psv(ttyp) ? 2 : /* passive */
462                                             32; /* active */
463                 if (init_fifo(&task->rcvdt.fifo, fifosz) < 0) {
464                         printk(KERN_ERR
465                                "omapdsp: unable to allocate receive buffer. "
466                                "(%d bytes for %s)\n", fifosz, task->name);
467                         ret = -ENOMEM;
468                         goto fail_out;
469                 }
470         } else {
471                 /* block */
472                 INIT_IPBLINK(&task->rcvdt.bk.link);
473                 task->rcvdt.bk.rp = 0;
474         }
475
476         /* write initialization */
477         spin_lock_init(&task->wsz_lock);
478         task->wsz = rcvtyp_acv(ttyp) ? 0 :              /* active */
479                     rcvtyp_wd(ttyp)  ? 2 :              /* passive word */
480                                        ipbcfg.lsz*2;    /* passive block */
481
482         return 0;
483
484 fail_out:
485         dsptask[tid] = NULL;
486         return ret;
487 }
488
489 static void dsp_task_init(struct dsptask *task)
490 {
491         dsp_mbsend(MBCMD(TCTL), task->tid, OMAP_DSP_MBCMD_TCTL_TINIT);
492 }
493
494 int dsp_task_config_all(unsigned char n)
495 {
496         int i, ret;
497         struct taskdev *devheap;
498         struct dsptask *taskheap;
499         size_t devheapsz, taskheapsz;
500
501         memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
502         memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
503
504         n_task = n;
505         printk(KERN_INFO "omapdsp: found %d task(s)\n", n_task);
506         if (n_task == 0)
507                 return 0;
508
509         /*
510          * reducing kmalloc!
511          */
512         devheapsz  = sizeof(struct taskdev) * n_task;
513         taskheapsz = sizeof(struct dsptask) * n_task;
514         heap = kmalloc(devheapsz + taskheapsz, GFP_KERNEL);
515         if (heap == NULL) {
516                 n_task = 0;
517                 return -ENOMEM;
518         }
519         memset(heap, 0, devheapsz + taskheapsz);
520         devheap  = heap;
521         taskheap = heap + devheapsz;
522
523         for (i = 0; i < n_task; i++) {
524                 struct taskdev *dev  = &devheap[i];
525                 struct dsptask *task = &taskheap[i];
526
527                 if ((ret = dsp_task_config(task, i)) < 0)
528                         return ret;
529                 if ((ret = taskdev_init(dev, task->name, i)) < 0)
530                         return ret;
531                 taskdev_attach_task(dev, task);
532                 dsp_task_init(task);
533                 printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
534         }
535
536         return 0;
537 }
538
539 static void dsp_task_unconfig(struct dsptask *task)
540 {
541         unsigned char tid = task->tid;
542
543         preempt_disable();
544         dsp_task_flush_buf(task);
545         if (sndtyp_wd(task->ttyp) && (task->state == TASK_STATE_READY))
546                 free_fifo(&task->rcvdt.fifo);
547         dsptask[tid] = NULL;
548         preempt_enable();
549 }
550
551 void dsp_task_unconfig_all(void)
552 {
553         unsigned char minor;
554         unsigned char tid;
555         struct dsptask *task;
556
557         for (minor = 0; minor < n_task; minor++) {
558                 /*
559                  * taskdev[minor] can be NULL in case of
560                  * configuration failure
561                  */
562                 if (taskdev[minor])
563                         taskdev_delete(minor);
564         }
565         for (; minor < TASKDEV_MAX; minor++) {
566                 if (taskdev[minor])
567                         dsp_rmdev_minor(minor);
568         }
569
570         for (tid = 0; tid < n_task; tid++) {
571                 /*
572                  * dsptask[tid] can be NULL in case of
573                  * configuration failure
574                  */
575                 task = dsptask[tid];
576                 if (task)
577                         dsp_task_unconfig(task);
578         }
579         for (; tid < TASKDEV_MAX; tid++) {
580                 task = dsptask[tid];
581                 if (task) {
582                         /*
583                          * on-demand tasks should be deleted in
584                          * rmdev_minor(), but just in case.
585                          */
586                         dsp_task_unconfig(task);
587                         kfree(task);
588                 }
589         }
590
591         if (heap) {
592                 kfree(heap);
593                 heap = NULL;
594         }
595
596         n_task = 0;
597 }
598
599 static struct device_driver dsptask_driver = {
600         .name   = "dsptask",
601         .bus    = &dsptask_bus,
602 };
603
604 unsigned char dsp_task_count(void)
605 {
606         return n_task;
607 }
608
609 int dsp_taskmod_busy(void)
610 {
611         struct taskdev *dev;
612         unsigned char minor;
613
614         for (minor = 0; minor < TASKDEV_MAX; minor++) {
615                 dev = taskdev[minor];
616                 if (dev == NULL)
617                         continue;
618                 if (dev->usecount > 0) {
619                         printk("dsp_taskmod_busy(): %s: usecount=%d\n",
620                                dev->name, dev->usecount);
621                         return 1;
622                 }
623 /*
624                 if ((dev->state & (OMAP_DSP_DEVSTATE_ADDREQ |
625                                    OMAP_DSP_DEVSTATE_DELREQ)) {
626 */
627                 if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ) {
628                         printk("dsp_taskmod_busy(): %s is in %s\n",
629                                dev->name, devstate_name(dev->state));
630                         return 1;
631                 }
632         }
633         return 0;
634 }
635
636 /*
637  * DSP task device file operations
638  */
639 static ssize_t dsp_task_read_wd_acv(struct file *file, char *buf, size_t count,
640                                     loff_t *ppos)
641 {
642         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
643         struct taskdev *dev = taskdev[minor];
644         int have_devstate_lock = 0;
645         int ret = 0;
646
647         if (count == 0) {
648                 return 0;
649         } else if (count & 0x1) {
650                 printk(KERN_ERR
651                        "omapdsp: odd count is illegal for DSP task device.\n");
652                 return -EINVAL;
653         }
654
655         if (down_tasksem_interruptible(dev, &dev->read_sem))
656                 return -ERESTARTSYS;
657         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
658                 ret = -ERESTARTSYS;
659                 goto up_out;
660         }
661         have_devstate_lock = 1;
662
663         if (fifo_empty(&dev->task->rcvdt.fifo)) {
664                 long current_state = current->state;
665                 DECLARE_WAITQUEUE(wait, current);
666
667                 set_current_state(TASK_INTERRUPTIBLE);
668                 add_wait_queue(&dev->read_wait_q, &wait);
669                 if (fifo_empty(&dev->task->rcvdt.fifo)) {       /* last check */
670                         devstate_unlock(dev);
671                         have_devstate_lock = 0;
672                         schedule();
673                 }
674                 set_current_state(current_state);
675                 remove_wait_queue(&dev->read_wait_q, &wait);
676                 if (signal_pending(current)) {
677                         ret = -ERESTARTSYS;
678                         goto up_out;
679                 }
680                 if (!have_devstate_lock) {
681                         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
682                                 ret = -ERESTARTSYS;
683                                 goto up_out;
684                         }
685                         have_devstate_lock = 1;
686                 }
687                 if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
688                         goto up_out;
689         }
690
691         ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
692
693 up_out:
694         if (have_devstate_lock)
695                 devstate_unlock(dev);
696         up(&dev->read_sem);
697         return ret;
698 }
699
700 static ssize_t dsp_task_read_bk_acv(struct file *file, char *buf, size_t count,
701                                     loff_t *ppos)
702 {
703         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
704         struct taskdev *dev = taskdev[minor];
705         struct rcvdt_bk_struct *rcvdt;
706         int have_devstate_lock = 0;
707         ssize_t ret = 0;
708
709         if (count == 0) {
710                 return 0;
711         } else if (count & 0x1) {
712                 printk(KERN_ERR
713                        "omapdsp: odd count is illegal for DSP task device.\n");
714                 return -EINVAL;
715         } else if ((int)buf & 0x1) {
716                 printk(KERN_ERR
717                        "omapdsp: buf should be word aligned for "
718                        "dsp_task_read().\n");
719                 return -EINVAL;
720         }
721
722         if (down_tasksem_interruptible(dev, &dev->read_sem))
723                 return -ERESTARTSYS;
724         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
725                 ret = -ERESTARTSYS;
726                 goto up_out;
727         }
728         have_devstate_lock = 1;
729
730         if (ipblink_empty(&dev->task->rcvdt.bk.link)) {
731                 long current_state;
732                 DECLARE_WAITQUEUE(wait, current);
733
734                 add_wait_queue(&dev->read_wait_q, &wait);
735                 current_state = current->state;
736                 set_current_state(TASK_INTERRUPTIBLE);
737                 if (ipblink_empty(&dev->task->rcvdt.bk.link)) { /* last check */
738                         devstate_unlock(dev);
739                         have_devstate_lock = 0;
740                         schedule();
741                 }
742                 set_current_state(current_state);
743                 remove_wait_queue(&dev->read_wait_q, &wait);
744                 if (signal_pending(current)) {
745                         ret = -ERESTARTSYS;
746                         goto up_out;
747                 }
748                 if (!have_devstate_lock) {
749                         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
750                                 ret = -ERESTARTSYS;
751                                 goto up_out;
752                         }
753                         have_devstate_lock = 1;
754                 }
755                 /* signal or 0-byte send from DSP */
756                 if (ipblink_empty(&dev->task->rcvdt.bk.link))
757                         goto up_out;
758         }
759
760         rcvdt = &dev->task->rcvdt.bk;
761         /* copy from delayed IPBUF */
762         if (sndtyp_pvt(dev->task->ttyp)) {
763                 /* private */
764                 if (!ipblink_empty(&rcvdt->link)) {
765                         struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
766                         unsigned char *base, *src;
767                         size_t bkcnt;
768
769                         if (dsp_mem_enable(ipbp) < 0) {
770                                 ret = -ERESTARTSYS;
771                                 goto up_out;
772                         }
773                         base = MKVIRT(ipbp->ah, ipbp->al);
774                         bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
775                         if (dsp_address_validate(base, bkcnt,
776                                                  "task %s read buffer",
777                                                  dev->task->name) < 0) {
778                                 ret = -ERESTARTSYS;
779                                 goto pv_out1;
780                         }
781                         if (dsp_mem_enable(base) < 0) {
782                                 ret = -ERESTARTSYS;
783                                 goto pv_out1;
784                         }
785                         src = base + rcvdt->rp;
786                         if (bkcnt > count) {
787                                 if (copy_to_user_dsp(buf, src, count)) {
788                                         ret = -EFAULT;
789                                         goto pv_out2;
790                                 }
791                                 ret = count;
792                                 rcvdt->rp += count;
793                         } else {
794                                 if (copy_to_user_dsp(buf, src, bkcnt)) {
795                                         ret = -EFAULT;
796                                         goto pv_out2;
797                                 }
798                                 ret = bkcnt;
799                                 spin_lock(&rcvdt->link.lock);
800                                 ipblink_del_pvt(&rcvdt->link);
801                                 spin_unlock(&rcvdt->link.lock);
802                                 release_ipbuf_pvt(ipbp);
803                                 rcvdt->rp = 0;
804                         }
805 pv_out2:
806                         dsp_mem_disable(src);
807 pv_out1:
808                         dsp_mem_disable(ipbp);
809                 }
810         } else {
811                 /* global */
812                 if (dsp_mem_enable_ipbuf() < 0) {
813                         ret = -ERESTARTSYS;
814                         goto up_out;
815                 }
816                 while (!ipblink_empty(&rcvdt->link)) {
817                         unsigned char *src;
818                         size_t bkcnt;
819                         unsigned short bid = rcvdt->link.top;
820                         struct ipbuf *ipbp = ipbuf[bid];
821
822                         src = ipbp->d + rcvdt->rp;
823                         bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp;
824                         if (bkcnt > count) {
825                                 if (copy_to_user_dsp(buf, src, count)) {
826                                         ret = -EFAULT;
827                                         goto gb_out;
828                                 }
829                                 ret += count;
830                                 rcvdt->rp += count;
831                                 break;
832                         } else {
833                                 if (copy_to_user_dsp(buf, src, bkcnt)) {
834                                         ret = -EFAULT;
835                                         goto gb_out;
836                                 }
837                                 ret += bkcnt;
838                                 buf += bkcnt;
839                                 count -= bkcnt;
840                                 spin_lock(&rcvdt->link.lock);
841                                 ipblink_del_top(&rcvdt->link, ipbuf);
842                                 spin_unlock(&rcvdt->link.lock);
843                                 unuse_ipbuf(bid);
844                                 rcvdt->rp = 0;
845                         }
846                 }
847 gb_out:
848                 dsp_mem_disable_ipbuf();
849         }
850
851 up_out:
852         if (have_devstate_lock)
853                 devstate_unlock(dev);
854         up(&dev->read_sem);
855         return ret;
856 }
857
858 static ssize_t dsp_task_read_wd_psv(struct file *file, char *buf, size_t count,
859                                     loff_t *ppos)
860 {
861         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
862         struct taskdev *dev = taskdev[minor];
863         struct mbcmd mb;
864         unsigned char tid;
865         int ret = 0;
866
867         if (count == 0) {
868                 return 0;
869         } else if (count & 0x1) {
870                 printk(KERN_ERR
871                        "omapdsp: odd count is illegal for DSP task device.\n");
872                 return -EINVAL;
873         } else {
874                 /* force! */
875                 count = 2;
876         }
877
878         if (down_tasksem_interruptible(dev, &dev->read_sem))
879                 return -ERESTARTSYS;
880         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
881                 ret = -ERESTARTSYS;
882                 goto up_out;
883         }
884         tid = dev->task->tid;
885         devstate_unlock(dev);
886
887         mbcmd_set(mb, MBCMD(WDREQ), tid, 0);
888         dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
889
890         if (signal_pending(current)) {
891                 ret = -ERESTARTSYS;
892                 goto up_out;
893         }
894         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
895                 ret = -ERESTARTSYS;
896                 goto up_out;
897         }
898         if (fifo_empty(&dev->task->rcvdt.fifo)) /* should not occur */
899                 goto unlock_out;
900
901         ret = copy_to_user_fm_fifo(buf, &dev->task->rcvdt.fifo, count);
902
903 unlock_out:
904         devstate_unlock(dev);
905 up_out:
906         up(&dev->read_sem);
907         return ret;
908 }
909
910 static ssize_t dsp_task_read_bk_psv(struct file *file, char *buf, size_t count,
911                                     loff_t *ppos)
912 {
913         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
914         struct taskdev *dev = taskdev[minor];
915         struct rcvdt_bk_struct *rcvdt;
916         struct mbcmd mb;
917         unsigned char tid;
918         int ret = 0;
919
920         if (count == 0) {
921                 return 0;
922         } else if (count & 0x1) {
923                 printk(KERN_ERR
924                        "omapdsp: odd count is illegal for DSP task device.\n");
925                 return -EINVAL;
926         } else if ((int)buf & 0x1) {
927                 printk(KERN_ERR
928                        "omapdsp: buf should be word aligned for "
929                        "dsp_task_read().\n");
930                 return -EINVAL;
931         }
932
933         if (down_tasksem_interruptible(dev, &dev->read_sem))
934                 return -ERESTARTSYS;
935         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
936                 ret = -ERESTARTSYS;
937                 goto up_out;
938         }
939         tid = dev->task->tid;
940         devstate_unlock(dev);
941
942         mbcmd_set(mb, MBCMD(BKREQ), tid, count/2);
943         dsp_mbcmd_send_and_wait(&mb, &dev->read_wait_q);
944
945         if (signal_pending(current)) {
946                 ret = -ERESTARTSYS;
947                 goto up_out;
948         }
949         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
950                 ret = -ERESTARTSYS;
951                 goto up_out;
952         }
953         rcvdt = &dev->task->rcvdt.bk;
954         /* signal or 0-byte send from DSP */
955         if (ipblink_empty(&rcvdt->link))
956                 goto unlock_out;
957
958         /*
959          * We will not receive more than requested count.
960          */
961         if (sndtyp_pvt(dev->task->ttyp)) {
962                 /* private */
963                 struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
964                 size_t rcvcnt;
965                 void *src;
966
967                 if (dsp_mem_enable(ipbp) < 0) {
968                         ret = -ERESTARTSYS;
969                         goto unlock_out;
970                 }
971                 src = MKVIRT(ipbp->ah, ipbp->al);
972                 rcvcnt = ((unsigned long)ipbp->c) * 2;
973                 if (dsp_address_validate(src, rcvcnt, "task %s read buffer",
974                                          dev->task->name) < 0) {
975                         ret = -ERESTARTSYS;
976                         goto pv_out1;
977                 }
978                 if (dsp_mem_enable(src) < 0) {
979                         ret = -ERESTARTSYS;
980                         goto pv_out1;
981                 }
982                 if (count > rcvcnt)
983                         count = rcvcnt;
984                 if (copy_to_user_dsp(buf, src, count)) {
985                         ret = -EFAULT;
986                         goto pv_out2;
987                 }
988                 spin_lock(&rcvdt->link.lock);
989                 ipblink_del_pvt(&rcvdt->link);
990                 spin_unlock(&rcvdt->link.lock);
991                 release_ipbuf_pvt(ipbp);
992                 ret = count;
993 pv_out2:
994                 dsp_mem_disable(src);
995 pv_out1:
996                 dsp_mem_disable(ipbp);
997         } else {
998                 /* global */
999                 unsigned short bid = rcvdt->link.top;
1000                 struct ipbuf *ipbp = ipbuf[bid];
1001                 size_t rcvcnt;
1002
1003                 if (dsp_mem_enable_ipbuf() < 0) {
1004                         ret = -ERESTARTSYS;
1005                         goto unlock_out;
1006                 }
1007                 rcvcnt = ((unsigned long)ipbp->c) * 2;
1008                 if (count > rcvcnt)
1009                         count = rcvcnt;
1010                 if (copy_to_user_dsp(buf, ipbp->d, count)) {
1011                         ret = -EFAULT;
1012                         goto gb_out;
1013                 }
1014                 spin_lock(&rcvdt->link.lock);
1015                 ipblink_del_top(&rcvdt->link, ipbuf);
1016                 spin_unlock(&rcvdt->link.lock);
1017                 unuse_ipbuf(bid);
1018                 ret = count;
1019 gb_out:
1020                 dsp_mem_disable_ipbuf();
1021         }
1022
1023 unlock_out:
1024         devstate_unlock(dev);
1025 up_out:
1026         up(&dev->read_sem);
1027         return ret;
1028 }
1029
1030 static ssize_t dsp_task_write_wd(struct file *file, const char *buf,
1031                                  size_t count, loff_t *ppos)
1032 {
1033         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
1034         struct taskdev *dev = taskdev[minor];
1035         unsigned short wd;
1036         int have_devstate_lock = 0;
1037         int ret = 0;
1038
1039         if (count == 0) {
1040                 return 0;
1041         } else if (count & 0x1) {
1042                 printk(KERN_ERR
1043                        "omapdsp: odd count is illegal for DSP task device.\n");
1044                 return -EINVAL;
1045         } else {
1046                 /* force! */
1047                 count = 2;
1048         }
1049
1050         if (down_tasksem_interruptible(dev, &dev->write_sem))
1051                 return -ERESTARTSYS;
1052         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
1053                 ret = -ERESTARTSYS;
1054                 goto up_out;
1055         }
1056         have_devstate_lock = 1;
1057
1058         if (dev->task->wsz == 0) {
1059                 long current_state;
1060                 DECLARE_WAITQUEUE(wait, current);
1061
1062                 add_wait_queue(&dev->write_wait_q, &wait);
1063                 current_state = current->state;
1064                 set_current_state(TASK_INTERRUPTIBLE);
1065                 if (dev->task->wsz == 0) {      /* last check */
1066                         devstate_unlock(dev);
1067                         have_devstate_lock = 0;
1068                         schedule();
1069                 }
1070                 set_current_state(current_state);
1071                 remove_wait_queue(&dev->write_wait_q, &wait);
1072                 if (signal_pending(current)) {
1073                         ret = -ERESTARTSYS;
1074                         goto up_out;
1075                 }
1076                 if (!have_devstate_lock) {
1077                         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
1078                                 ret = -ERESTARTSYS;
1079                                 goto up_out;
1080                         }
1081                         have_devstate_lock = 1;
1082                 }
1083                 if (dev->task->wsz == 0)        /* should not occur */
1084                         goto up_out;
1085         }
1086
1087         if (copy_from_user(&wd, buf, count)) {
1088                 ret = -EFAULT;
1089                 goto up_out;
1090         }
1091
1092         spin_lock(&dev->task->wsz_lock);
1093         if (dsp_mbsend(MBCMD(WDSND), dev->task->tid, wd) < 0) {
1094                 spin_unlock(&dev->task->wsz_lock);
1095                 goto up_out;
1096         }
1097         ret = count;
1098         if (rcvtyp_acv(dev->task->ttyp))
1099                 dev->task->wsz = 0;
1100         spin_unlock(&dev->task->wsz_lock);
1101
1102 up_out:
1103         if (have_devstate_lock)
1104                 devstate_unlock(dev);
1105         up(&dev->write_sem);
1106         return ret;
1107 }
1108
1109 static ssize_t dsp_task_write_bk(struct file *file, const char *buf,
1110                                  size_t count, loff_t *ppos)
1111 {
1112         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
1113         struct taskdev *dev = taskdev[minor];
1114         int have_devstate_lock = 0;
1115         int ret = 0;
1116
1117         if (count == 0) {
1118                 return 0;
1119         } else if (count & 0x1) {
1120                 printk(KERN_ERR
1121                        "omapdsp: odd count is illegal for DSP task device.\n");
1122                 return -EINVAL;
1123         } else if ((int)buf & 0x1) {
1124                 printk(KERN_ERR
1125                        "omapdsp: buf should be word aligned for "
1126                        "dsp_task_write().\n");
1127                 return -EINVAL;
1128         }
1129
1130         if (down_tasksem_interruptible(dev, &dev->write_sem))
1131                 return -ERESTARTSYS;
1132         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
1133                 ret = -ERESTARTSYS;
1134                 goto up_out;
1135         }
1136         have_devstate_lock = 1;
1137
1138         if (dev->task->wsz == 0) {
1139                 long current_state;
1140                 DECLARE_WAITQUEUE(wait, current);
1141
1142                 add_wait_queue(&dev->write_wait_q, &wait);
1143                 current_state = current->state;
1144                 set_current_state(TASK_INTERRUPTIBLE);
1145                 if (dev->task->wsz == 0) {      /* last check */
1146                         devstate_unlock(dev);
1147                         have_devstate_lock = 0;
1148                         schedule();
1149                 }
1150                 set_current_state(current_state);
1151                 remove_wait_queue(&dev->write_wait_q, &wait);
1152                 if (signal_pending(current)) {
1153                         ret = -ERESTARTSYS;
1154                         goto up_out;
1155                 }
1156                 if (!have_devstate_lock) {
1157                         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
1158                                 ret = -ERESTARTSYS;
1159                                 goto up_out;
1160                         }
1161                         have_devstate_lock = 1;
1162                 }
1163                 if (dev->task->wsz == 0)        /* should not occur */
1164                         goto up_out;
1165         }
1166
1167         if (count > dev->task->wsz)
1168                 count = dev->task->wsz;
1169
1170         if (rcvtyp_pvt(dev->task->ttyp)) {
1171                 /* private */
1172                 struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w;
1173                 unsigned char *dst;
1174
1175                 if (dsp_mem_enable(ipbp) < 0) {
1176                         ret = -ERESTARTSYS;
1177                         goto up_out;
1178                 }
1179                 dst = MKVIRT(ipbp->ah, ipbp->al);
1180                 if (dsp_address_validate(dst, count, "task %s write buffer",
1181                                          dev->task->name) < 0) {
1182                         ret = -ERESTARTSYS;
1183                         goto pv_out1;
1184                 }
1185                 if (dsp_mem_enable(dst) < 0) {
1186                         ret = -ERESTARTSYS;
1187                         goto pv_out1;
1188                 }
1189                 if (copy_from_user_dsp(dst, buf, count)) {
1190                         ret = -EFAULT;
1191                         goto pv_out2;
1192                 }
1193                 ipbp->c = count/2;
1194                 ipbp->s = dev->task->tid;
1195                 spin_lock(&dev->task->wsz_lock);
1196                 if (dsp_mbsend(MBCMD(BKSNDP), dev->task->tid, 0) == 0) {
1197                         if (rcvtyp_acv(dev->task->ttyp))
1198                                 dev->task->wsz = 0;
1199                         ret = count;
1200                 }
1201                 spin_unlock(&dev->task->wsz_lock);
1202 pv_out2:
1203                 dsp_mem_disable(dst);
1204 pv_out1:
1205                 dsp_mem_disable(ipbp);
1206         } else {
1207                 /* global */
1208                 struct ipbuf *ipbp;
1209                 unsigned short bid;
1210
1211                 if (dsp_mem_enable_ipbuf() < 0) {
1212                         ret = -ERESTARTSYS;
1213                         goto up_out;
1214                 }
1215                 bid = get_free_ipbuf(dev->task->tid);
1216                 if (bid == OMAP_DSP_BID_NULL)
1217                         goto gb_out;
1218                 ipbp = ipbuf[bid];
1219                 if (copy_from_user_dsp(ipbp->d, buf, count)) {
1220                         release_ipbuf(bid);
1221                         ret = -EFAULT;
1222                         goto gb_out;
1223                 }
1224                 ipbp->c  = count/2;
1225                 ipbp->sa = dev->task->tid;
1226                 spin_lock(&dev->task->wsz_lock);
1227                 if (dsp_mbsend(MBCMD(BKSND), dev->task->tid, bid) == 0) {
1228                         if (rcvtyp_acv(dev->task->ttyp))
1229                                 dev->task->wsz = 0;
1230                         ret = count;
1231                         ipb_bsycnt_inc(&ipbcfg);
1232                 } else
1233                         release_ipbuf(bid);
1234                 spin_unlock(&dev->task->wsz_lock);
1235 gb_out:
1236                 dsp_mem_disable_ipbuf();
1237         }
1238
1239 up_out:
1240         if (have_devstate_lock)
1241                 devstate_unlock(dev);
1242         up(&dev->write_sem);
1243         return ret;
1244 }
1245
1246 static unsigned int dsp_task_poll(struct file * file, poll_table * wait)
1247 {
1248         unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
1249         struct taskdev *dev = taskdev[minor];
1250         struct dsptask *task = dev->task;
1251         unsigned int mask = 0;
1252
1253         poll_wait(file, &dev->read_wait_q, wait);
1254         poll_wait(file, &dev->write_wait_q, wait);
1255         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
1256                 return 0;
1257         if (sndtyp_psv(task->ttyp) ||
1258             (sndtyp_wd(task->ttyp) && !fifo_empty(&task->rcvdt.fifo)) ||
1259             (sndtyp_bk(task->ttyp) && !ipblink_empty(&task->rcvdt.bk.link)))
1260                 mask |= POLLIN | POLLRDNORM;
1261         if (task->wsz)
1262                 mask |= POLLOUT | POLLWRNORM;
1263         devstate_unlock(dev);
1264
1265         return mask;
1266 }
1267
1268 static int dsp_task_ioctl(struct inode *inode, struct file *file,
1269                           unsigned int cmd, unsigned long arg)
1270 {
1271         unsigned int minor = MINOR(inode->i_rdev);
1272         struct taskdev *dev = taskdev[minor];
1273         struct mbcmd mb;
1274         unsigned char tid;
1275         struct mb_exarg mbarg, *mbargp;
1276         int mbargc;
1277         unsigned short mbargv[1];
1278         int interactive;
1279         int ret;
1280
1281         /* LOCK / UNLOCK operations */
1282         switch (cmd) {
1283         case OMAP_DSP_TASK_IOCTL_LOCK:
1284                 return taskdev_lock(dev);
1285         case OMAP_DSP_TASK_IOCTL_UNLOCK:
1286                 return taskdev_unlock(dev);
1287         }
1288
1289         /*
1290          * actually only interractive commands need to lock
1291          * the semaphore, but here all commands do it for simplicity.
1292          */
1293         if (down_tasksem_interruptible(dev, &dev->ioctl_sem))
1294                 return -ERESTARTSYS;
1295         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
1296                 ret = -ERESTARTSYS;
1297                 goto up_out;
1298         }
1299
1300         if ((cmd >= 0x0080) && (cmd < 0x0100)) {
1301                 /*
1302                  * 0x0080 - 0x00ff
1303                  * reserved for backward compatibility
1304                  * user-defined TCTL commands: no arg, non-interactive
1305                  */
1306                 printk(KERN_WARNING "omapdsp: "
1307                        "TCTL commands in 0x0080 - 0x0100 are obsolete.\n"
1308                        "they won't be supported in the future.\n");
1309                 mbargc = 0;
1310                 interactive = 0;
1311         } else if (cmd < 0x8000) {
1312                 /*
1313                  * 0x0000 - 0x7fff (except 0x0080 - 0x00ff)
1314                  * system reserved TCTL commands
1315                  */
1316                 switch (cmd) {
1317                 case OMAP_DSP_MBCMD_TCTL_TEN:
1318                 case OMAP_DSP_MBCMD_TCTL_TDIS:
1319                         mbargc = 0;
1320                         interactive = 0;
1321                         break;
1322                 default:
1323                         ret = -ENOIOCTLCMD;
1324                         goto unlock_out;
1325                 }
1326         }
1327         /*
1328          * 0x8000 - 0xffff
1329          * user-defined TCTL commands
1330          */
1331         else if (cmd < 0x8100) {
1332                 /* 0x8000-0x80ff: no arg, non-interactive */
1333                 mbargc = 0;
1334                 interactive = 0;
1335         } else if (cmd < 0x8200) {
1336                 /* 0x8100-0x81ff: 1 arg, non-interactive */
1337                 mbargc = 1;
1338                 mbargv[0] = arg & 0xffff;
1339                 interactive = 0;
1340         } else if (cmd < 0x9000) {
1341                 /* 0x8200-0x8fff: reserved */
1342                 ret = -ENOIOCTLCMD;
1343                 goto unlock_out;
1344         } else if (cmd < 0x9100) {
1345                 /* 0x9000-0x90ff: no arg, interactive */
1346                 mbargc = 0;
1347                 interactive = 1;
1348         } else if (cmd < 0x9200) {
1349                 /* 0x9100-0x91ff: 1 arg, interactive */
1350                 mbargc = 1;
1351                 mbargv[0] = arg & 0xffff;
1352                 interactive = 1;
1353         } else if (cmd < 0x10000) {
1354                 /* 0x9200-0xffff: reserved */
1355                 ret =  -ENOIOCTLCMD;
1356                 goto unlock_out;
1357         } else {
1358                 /*
1359                  * 0x10000 -
1360                  * non TCTL ioctls
1361                  */
1362                 switch (cmd) {
1363                 case OMAP_DSP_TASK_IOCTL_BFLSH:
1364                         ret = dsp_task_flush_buf(dev->task);
1365                         break;
1366                 case OMAP_DSP_TASK_IOCTL_SETBSZ:
1367                         ret = dsp_task_set_fifosz(dev->task, arg);
1368                         break;
1369                 case OMAP_DSP_TASK_IOCTL_GETNAME:
1370                         ret = 0;
1371                         if (copy_to_user((void *)arg, dev->name,
1372                                          strlen(dev->name) + 1))
1373                                 ret = -EFAULT;
1374                         break;
1375                 default:
1376                         ret = -ENOIOCTLCMD;
1377                 }
1378                 goto unlock_out;
1379         }
1380
1381         /*
1382          * issue TCTL
1383          */
1384         tid = dev->task->tid;
1385         mbcmd_set(mb, MBCMD(TCTL), tid, cmd);
1386         if (mbargc > 0) {
1387                 mbarg.argc = mbargc;
1388                 mbarg.tid  = tid;
1389                 mbarg.argv = mbargv;
1390                 mbargp = &mbarg;
1391         } else
1392                 mbargp = NULL;
1393
1394         if (interactive) {
1395                 dev->task->tctl_stat = -ERESTARTSYS;
1396                 devstate_unlock(dev);
1397
1398                 dsp_mbcmd_send_and_wait_exarg(&mb, mbargp, &dev->ioctl_wait_q);
1399                 if (signal_pending(current)) {
1400                         ret = -ERESTARTSYS;
1401                         goto up_out;
1402                 }
1403                 if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0) {
1404                         ret = -ERESTARTSYS;
1405                         goto up_out;
1406                 }
1407                 ret = dev->task->tctl_stat;
1408                 if (ret < 0) {
1409                         printk(KERN_ERR "omapdsp: TCTL not responding.\n");
1410                         goto unlock_out;
1411                 }
1412         } else {
1413                 dsp_mbcmd_send_exarg(&mb, mbargp);
1414                 ret = 0;
1415         }
1416
1417 unlock_out:
1418         devstate_unlock(dev);
1419 up_out:
1420         up(&dev->ioctl_sem);
1421         return ret;
1422 }
1423
1424 static void dsp_task_mmap_open(struct vm_area_struct *vma)
1425 {
1426         struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
1427         struct dsptask *task;
1428         size_t len = vma->vm_end - vma->vm_start;
1429
1430         BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
1431         task = dev->task;
1432         exmap_use(task->map_base, len);
1433 }
1434
1435 static void dsp_task_mmap_close(struct vm_area_struct *vma)
1436 {
1437         struct taskdev *dev = (struct taskdev *)vma->vm_private_data;
1438         struct dsptask *task;
1439         size_t len = vma->vm_end - vma->vm_start;
1440
1441         BUG_ON(!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED));
1442         task = dev->task;
1443         exmap_unuse(task->map_base, len);
1444 }
1445
1446 /**
1447  * On demand page allocation is not allowed. The mapping area is defined by
1448  * corresponding DSP tasks.
1449  */
1450 static struct page *dsp_task_mmap_nopage(struct vm_area_struct *vma,
1451                                          unsigned long address, int *type)
1452 {
1453         return NOPAGE_SIGBUS;
1454 }
1455
1456 static struct vm_operations_struct dsp_task_vm_ops = {
1457         .open = dsp_task_mmap_open,
1458         .close = dsp_task_mmap_close,
1459         .nopage = dsp_task_mmap_nopage,
1460 };
1461
1462 static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma)
1463 {
1464         void *tmp_vadr;
1465         unsigned long tmp_padr, tmp_vmadr, off;
1466         size_t req_len, tmp_len;
1467         unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
1468         struct taskdev *dev = taskdev[minor];
1469         struct dsptask *task;
1470         int ret = 0;
1471
1472         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED) < 0)
1473                 return -ERESTARTSYS;
1474         task = dev->task;
1475
1476         /*
1477          * Don't swap this area out
1478          * Don't dump this area to a core file
1479          */
1480         vma->vm_flags |= VM_RESERVED | VM_IO;
1481
1482         /* Do not cache this area */
1483         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1484
1485         req_len = vma->vm_end - vma->vm_start;
1486         off = vma->vm_pgoff << PAGE_SHIFT;
1487         tmp_vmadr = vma->vm_start;
1488         tmp_vadr = task->map_base + off;
1489         do {
1490                 tmp_padr = dsp_virt_to_phys(tmp_vadr, &tmp_len);
1491                 if (tmp_padr == 0) {
1492                         printk(KERN_ERR
1493                                "omapdsp: task %s: illegal address "
1494                                "for mmap: %p", task->name, tmp_vadr);
1495                         /* partial mapping will be cleared in upper layer */
1496                         ret = -EINVAL;
1497                         goto unlock_out;
1498                 }
1499                 if (tmp_len > req_len)
1500                         tmp_len = req_len;
1501
1502                 printk(KERN_DEBUG
1503                        "omapdsp: mmap info: "
1504                        "vmadr = %08lx, padr = %08lx, len = %x\n",
1505                        tmp_vmadr, tmp_padr, tmp_len);
1506                 if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT,
1507                                     tmp_len, vma->vm_page_prot) != 0) {
1508                         printk(KERN_ERR
1509                                "omapdsp: task %s: remap_page_range() failed.\n",
1510                                task->name);
1511                         /* partial mapping will be cleared in upper layer */
1512                         ret = -EINVAL;
1513                         goto unlock_out;
1514                 }
1515
1516                 req_len   -= tmp_len;
1517                 tmp_vmadr += tmp_len;
1518                 tmp_vadr  += tmp_len;
1519         } while (req_len);
1520
1521         vma->vm_ops = &dsp_task_vm_ops;
1522         vma->vm_private_data = dev;
1523         exmap_use(task->map_base, vma->vm_end - vma->vm_start);
1524
1525 unlock_out:
1526         devstate_unlock(dev);
1527         return ret;
1528 }
1529
1530 static int dsp_task_open(struct inode *inode, struct file *file)
1531 {
1532         unsigned int minor = MINOR(inode->i_rdev);
1533         struct taskdev *dev;
1534         int ret = 0;
1535
1536         if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL))
1537                 return -ENODEV;
1538         if (devstate_lock(dev, OMAP_DSP_DEVSTATE_NOTASK |
1539                                OMAP_DSP_DEVSTATE_ATTACHED) < 0)
1540                 return -ERESTARTSYS;
1541 #ifndef CONFIG_OMAP_DSP_TASK_MULTIOPEN
1542         if (dev->usecount > 0) {
1543                 ret = -EBUSY;
1544                 goto unlock_out;
1545         }
1546 #endif
1547
1548         if (dev->state & OMAP_DSP_DEVSTATE_NOTASK) {
1549                 dev->state = OMAP_DSP_DEVSTATE_ADDREQ;
1550                 /* wake up twch daemon for tadd */
1551                 dsp_twch_touch();
1552                 devstate_unlock(dev);
1553                 if (devstate_lock(dev, OMAP_DSP_DEVSTATE_ATTACHED |
1554                                        OMAP_DSP_DEVSTATE_ADDFAIL) < 0) {
1555                         spin_lock(&dev->state_lock);
1556                         if (dev->state & OMAP_DSP_DEVSTATE_ADDREQ)
1557                                 dev->state = OMAP_DSP_DEVSTATE_NOTASK;
1558                         spin_unlock(&dev->state_lock);
1559                         return -ERESTARTSYS;
1560                 }
1561                 if (dev->state & OMAP_DSP_DEVSTATE_ADDFAIL) {
1562                         printk(KERN_ERR "omapdsp: task attach failed for %s!\n",
1563                                dev->name);
1564                         ret = -EBUSY;
1565                         dev->state = OMAP_DSP_DEVSTATE_NOTASK;
1566                         wake_up_interruptible_all(&dev->state_wait_q);
1567                         goto unlock_out;
1568                 }
1569         }
1570
1571         /* state_lock covers usecount, proc_list as well. */
1572         dev->usecount++;
1573         proc_list_add(&dev->proc_list, current);
1574         file->f_op = &dev->fops;
1575         devstate_unlock(dev);
1576
1577         return 0;
1578
1579 unlock_out:
1580         devstate_unlock(dev);
1581         return ret;
1582 }
1583
1584 static int dsp_task_release(struct inode *inode, struct file *file)
1585 {
1586         unsigned int minor = MINOR(inode->i_rdev);
1587         struct taskdev *dev = taskdev[minor];
1588
1589         /* state_lock covers usecount, proc_list as well. */
1590         spin_lock(&dev->state_lock);
1591
1592         /* state can be ATTACHED, KILLING or GARBAGE here. */
1593         switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
1594
1595         case OMAP_DSP_DEVSTATE_KILLING:
1596                 dev->usecount--;
1597                 break;
1598
1599         case OMAP_DSP_DEVSTATE_GARBAGE:
1600                 if(--dev->usecount == 0) {
1601                         dev->state = OMAP_DSP_DEVSTATE_NOTASK;
1602                         wake_up_interruptible_all(&dev->state_wait_q);
1603                 }
1604                 break;
1605
1606         case OMAP_DSP_DEVSTATE_ATTACHED:
1607                 if (dev->lock_pid == current->pid)
1608                         taskdev_unlock(dev);
1609                 proc_list_del(&dev->proc_list, current);
1610                 if (--dev->usecount == 0) {
1611                         if (minor >= n_task) {  /* dynamic task */
1612                                 dev->state = OMAP_DSP_DEVSTATE_DELREQ;
1613                                 /* wake up twch daemon for tdel */
1614                                 dsp_twch_touch();
1615                         }
1616                 }
1617                 break;
1618
1619         }
1620
1621         spin_unlock(&dev->state_lock);
1622         return 0;
1623 }
1624
1625 /*
1626  * mkdev / rmdev
1627  */
1628 int dsp_mkdev(char *name)
1629 {
1630         struct taskdev *dev;
1631         int status;
1632         unsigned char minor;
1633
1634         if (!dsp_is_ready()) {
1635                 printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
1636                 return -EINVAL;
1637         }
1638         for (minor = n_task; minor < TASKDEV_MAX; minor++) {
1639                 if (taskdev[minor] == NULL)
1640                         goto do_make;
1641         }
1642         printk(KERN_ERR "omapdsp: Too many task devices.\n");
1643         return -EBUSY;
1644
1645 do_make:
1646         if ((dev = kmalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL)
1647                 return -ENOMEM;
1648         memset(dev, 0, sizeof(struct taskdev));
1649         if ((status = taskdev_init(dev, name, minor)) < 0) {
1650                 kfree(dev);
1651                 return status;
1652         }
1653         return minor;
1654 }
1655
1656 int dsp_rmdev(char *name)
1657 {
1658         unsigned char minor;
1659         int ret;
1660
1661         if (!dsp_is_ready()) {
1662                 printk(KERN_ERR "omapdsp: dsp has not been configured.\n");
1663                 return -EINVAL;
1664         }
1665         for (minor = n_task; minor < TASKDEV_MAX; minor++) {
1666                 if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) {
1667                         if ((ret = dsp_rmdev_minor(minor)) < 0)
1668                                 return ret;
1669                         return minor;
1670                 }
1671         }
1672         return -EINVAL;
1673 }
1674
1675 static int dsp_rmdev_minor(unsigned char minor)
1676 {
1677         struct taskdev *dev = taskdev[minor];
1678
1679         spin_lock(&dev->state_lock);
1680
1681         switch (dev->state & OMAP_DSP_DEVSTATE_STATE_MASK) {
1682
1683         case OMAP_DSP_DEVSTATE_NOTASK:
1684                 /* fine */
1685                 break;
1686
1687         case OMAP_DSP_DEVSTATE_ATTACHED:
1688                 /* task is working. kill it. */
1689                 dev->state = OMAP_DSP_DEVSTATE_KILLING;
1690                 proclist_send_sigbus(&dev->proc_list);
1691                 spin_unlock(&dev->state_lock);
1692                 dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
1693                 goto invalidate;
1694
1695         case OMAP_DSP_DEVSTATE_ADDREQ:
1696                 /* open() is waiting. drain it. */
1697                 dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
1698                 wake_up_interruptible_all(&dev->state_wait_q);
1699                 break;
1700
1701         case OMAP_DSP_DEVSTATE_DELREQ:
1702                 /* nobody is waiting. */
1703                 dev->state = OMAP_DSP_DEVSTATE_NOTASK;
1704                 wake_up_interruptible_all(&dev->state_wait_q);
1705                 break;
1706
1707         case OMAP_DSP_DEVSTATE_ADDING:
1708         case OMAP_DSP_DEVSTATE_DELING:
1709         case OMAP_DSP_DEVSTATE_KILLING:
1710         case OMAP_DSP_DEVSTATE_GARBAGE:
1711         case OMAP_DSP_DEVSTATE_ADDFAIL:
1712                 /* transient state. wait for a moment. */
1713                 break;
1714
1715         }
1716
1717         spin_unlock(&dev->state_lock);
1718
1719 invalidate:
1720         /* wait for some time and hope the state is settled */
1721         devstate_lock_timeout(dev, OMAP_DSP_DEVSTATE_NOTASK, HZ);
1722         if (!(dev->state & OMAP_DSP_DEVSTATE_NOTASK)) {
1723                 printk(KERN_WARNING
1724                        "omapdsp: illegal device state (%s) on rmdev %s.\n",
1725                        devstate_name(dev->state), dev->name);
1726         }
1727         dev->state = OMAP_DSP_DEVSTATE_INVALID;
1728         devstate_unlock(dev);
1729
1730         taskdev_delete(minor);
1731         kfree(dev);
1732
1733         return 0;
1734 }
1735
1736 struct file_operations dsp_task_fops = {
1737         .owner   = THIS_MODULE,
1738         .poll    = dsp_task_poll,
1739         .ioctl   = dsp_task_ioctl,
1740         .open    = dsp_task_open,
1741         .release = dsp_task_release,
1742 };
1743
1744 static void dsptask_dev_release(struct device *dev)
1745 {
1746 }
1747
1748 static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor)
1749 {
1750         struct class_device *cdev;
1751
1752         taskdev[minor] = dev;
1753
1754         INIT_LIST_HEAD(&dev->proc_list);
1755         init_waitqueue_head(&dev->read_wait_q);
1756         init_waitqueue_head(&dev->write_wait_q);
1757         init_waitqueue_head(&dev->ioctl_wait_q);
1758         init_MUTEX(&dev->read_sem);
1759         init_MUTEX(&dev->write_sem);
1760         init_MUTEX(&dev->ioctl_sem);
1761         init_MUTEX(&dev->lock_sem);
1762         dev->lock_pid = 0;
1763
1764         strncpy(dev->name, name, OMAP_DSP_TNM_LEN);
1765         dev->name[OMAP_DSP_TNM_LEN-1] = '\0';
1766         dev->state = (minor < n_task) ? OMAP_DSP_DEVSTATE_ATTACHED :
1767                                         OMAP_DSP_DEVSTATE_NOTASK;
1768         dev->usecount = 0;
1769         memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations));
1770
1771         dev->dev.parent = &dsp_device.dev;
1772         dev->dev.bus = &dsptask_bus;
1773         sprintf(dev->dev.bus_id, "dsptask%d", minor);
1774         dev->dev.release = dsptask_dev_release;
1775         device_register(&dev->dev);
1776         device_create_file(&dev->dev, &dev_attr_devname);
1777         device_create_file(&dev->dev, &dev_attr_devstate);
1778         device_create_file(&dev->dev, &dev_attr_proc_list);
1779         cdev = class_device_create(dsp_task_class, NULL,
1780                                    MKDEV(OMAP_DSP_TASK_MAJOR, minor),
1781                                    NULL, "dsptask%d", minor);
1782
1783         init_waitqueue_head(&dev->state_wait_q);
1784         spin_lock_init(&dev->state_lock);
1785
1786         return 0;
1787 }
1788
1789 static void taskdev_delete(unsigned char minor)
1790 {
1791         struct taskdev *dev = taskdev[minor];
1792
1793         if (!dev)
1794                 return;
1795         device_remove_file(&dev->dev, &dev_attr_devname);
1796         device_remove_file(&dev->dev, &dev_attr_devstate);
1797         device_remove_file(&dev->dev, &dev_attr_proc_list);
1798         class_device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor));
1799         device_unregister(&dev->dev);
1800         proc_list_flush(&dev->proc_list);
1801         taskdev[minor] = NULL;
1802 }
1803
1804 static void taskdev_attach_task(struct taskdev *dev, struct dsptask *task)
1805 {
1806         unsigned short ttyp = task->ttyp;
1807
1808         dev->task = task;
1809         task->dev = dev;
1810         dev->fops.read =
1811                 sndtyp_acv(ttyp) ?
1812                         sndtyp_wd(ttyp) ? dsp_task_read_wd_acv:
1813                         /* sndtyp_bk */   dsp_task_read_bk_acv:
1814                 /* sndtyp_psv */
1815                         sndtyp_wd(ttyp) ? dsp_task_read_wd_psv:
1816                         /* sndtyp_bk */   dsp_task_read_bk_psv;
1817         dev->fops.write =
1818                 rcvtyp_wd(ttyp) ? dsp_task_write_wd:
1819                 /* rcvbyp_bk */   dsp_task_write_bk;
1820         if (task->map_length)
1821                 dev->fops.mmap = dsp_task_mmap;
1822
1823         device_create_file(&dev->dev, &dev_attr_taskname);
1824         device_create_file(&dev->dev, &dev_attr_ttyp);
1825         if (sndtyp_wd(ttyp)) {
1826                 device_create_file(&dev->dev, &dev_attr_fifosz);
1827                 device_create_file(&dev->dev, &dev_attr_fifocnt);
1828         } else
1829                 device_create_file(&dev->dev, &dev_attr_ipblink);
1830         device_create_file(&dev->dev, &dev_attr_wsz);
1831         if (task->map_length)
1832                 device_create_file(&dev->dev, &dev_attr_mmap);
1833 }
1834
1835 static void taskdev_detach_task(struct taskdev *dev)
1836 {
1837         unsigned short ttyp = dev->task->ttyp;
1838
1839         device_remove_file(&dev->dev, &dev_attr_taskname);
1840         device_remove_file(&dev->dev, &dev_attr_ttyp);
1841         if (sndtyp_wd(ttyp)) {
1842                 device_remove_file(&dev->dev, &dev_attr_fifosz);
1843                 device_remove_file(&dev->dev, &dev_attr_fifocnt);
1844         } else
1845                 device_remove_file(&dev->dev, &dev_attr_ipblink);
1846         device_remove_file(&dev->dev, &dev_attr_wsz);
1847         if (dev->task->map_length)
1848                 device_remove_file(&dev->dev, &dev_attr_mmap);
1849
1850         if (dev->task) {
1851                 dev->task = NULL;
1852                 dev->fops.read = NULL;
1853                 dev->fops.write = NULL;
1854                 printk(KERN_INFO "omapdsp: taskdev %s disabled.\n", dev->name);
1855         }
1856 }
1857
1858 /*
1859  * tadd / tdel / tkill
1860  */
1861 int dsp_tadd(unsigned char minor, unsigned long adr)
1862 {
1863         struct taskdev *dev;
1864         struct dsptask *task;
1865         struct mbcmd mb;
1866         struct mb_exarg arg;
1867         unsigned char tid, tid_response;
1868         unsigned short argv[2];
1869         int ret = minor;
1870
1871         if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
1872                 printk(KERN_ERR
1873                        "omapdsp: no task device with minor %d\n", minor);
1874                 return -EINVAL;
1875         }
1876
1877         spin_lock(&dev->state_lock);
1878         if (!(dev->state & OMAP_DSP_DEVSTATE_ADDREQ)) {
1879                 printk(KERN_ERR
1880                        "omapdsp: taskdev %s is not requesting for tadd. "
1881                        "(state is %s)\n", dev->name, devstate_name(dev->state));
1882                 spin_unlock(&dev->state_lock);
1883                 return -EINVAL;
1884         }
1885         dev->state = OMAP_DSP_DEVSTATE_ADDING;
1886         spin_unlock(&dev->state_lock);
1887
1888         if (adr == OMAP_DSP_TADD_ABORTADR) {
1889                 /* aborting tadd intentionally */
1890                 printk(KERN_INFO "omapdsp: tadd address is ABORTADR.\n");
1891                 goto fail_out;
1892         }
1893         if (adr >= DSPSPACE_SIZE) {
1894                 printk(KERN_ERR
1895                        "omapdsp: illegal address 0x%08lx for tadd\n", adr);
1896                 ret = -EINVAL;
1897                 goto fail_out;
1898         }
1899
1900         adr >>= 1;      /* word address */
1901         argv[0] = adr >> 16;    /* addrh */
1902         argv[1] = adr & 0xffff; /* addrl */
1903
1904         if (down_interruptible(&cfg_sem)) {
1905                 ret = -ERESTARTSYS;
1906                 goto fail_out;
1907         }
1908         cfg_tid = OMAP_DSP_TID_ANON;
1909         cfg_cmd = MBCMD(TADD);
1910         mbcmd_set(mb, MBCMD(TADD), 0, 0);
1911         arg.tid  = OMAP_DSP_TID_ANON;
1912         arg.argc = 2;
1913         arg.argv = argv;
1914
1915         dsp_mem_sync_inc();
1916         dsp_mbcmd_send_and_wait_exarg(&mb, &arg, &cfg_wait_q);
1917
1918         tid = cfg_tid;
1919         cfg_tid = OMAP_DSP_TID_ANON;
1920         cfg_cmd = 0;
1921         up(&cfg_sem);
1922
1923         if (tid == OMAP_DSP_TID_ANON) {
1924                 printk(KERN_ERR "omapdsp: tadd failed!\n");
1925                 ret = -EINVAL;
1926                 goto fail_out;
1927         }
1928         if ((tid < n_task) || dsptask[tid]) {
1929                 printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid);
1930                 ret = -EINVAL;
1931                 goto fail_out;
1932         }
1933         if ((task = kmalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) {
1934                 ret = -ENOMEM;
1935                 goto del_out;
1936         }
1937         memset(task, 0, sizeof(struct dsptask));
1938
1939         if ((ret = dsp_task_config(task, tid)) < 0)
1940                 goto free_out;
1941         taskdev_attach_task(dev, task);
1942
1943         if (strcmp(dev->name, task->name)) {
1944                 printk(KERN_ERR
1945                        "omapdsp: task name (%s) doesn't match with "
1946                        "device name (%s).\n", task->name, dev->name);
1947                 ret = -EINVAL;
1948                 goto free_out;
1949         }
1950
1951         dsp_task_init(task);
1952         printk(KERN_INFO "omapdsp: taskdev %s enabled.\n", dev->name);
1953         dev->state = OMAP_DSP_DEVSTATE_ATTACHED;
1954         wake_up_interruptible_all(&dev->state_wait_q);
1955         return minor;
1956
1957 free_out:
1958         kfree(task);
1959
1960 del_out:
1961         printk(KERN_ERR "omapdsp: deleting the task...\n");
1962
1963         dev->state = OMAP_DSP_DEVSTATE_DELING;
1964
1965         if (down_interruptible(&cfg_sem)) {
1966                 printk(KERN_ERR "omapdsp: aborting tdel process. "
1967                                 "DSP side could be corrupted.\n");
1968                 goto fail_out;
1969         }
1970         cfg_tid = OMAP_DSP_TID_ANON;
1971         cfg_cmd = MBCMD(TDEL);
1972         mbcmd_set(mb, MBCMD(TDEL), tid, OMAP_DSP_MBCMD_TDEL_KILL);
1973         dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
1974         tid_response = cfg_tid;
1975         cfg_tid = OMAP_DSP_TID_ANON;
1976         cfg_cmd = 0;
1977         up(&cfg_sem);
1978
1979         if (tid_response != tid)
1980                 printk(KERN_ERR "omapdsp: tdel failed. "
1981                                 "DSP side could be corrupted.\n");
1982
1983 fail_out:
1984         dev->state = OMAP_DSP_DEVSTATE_ADDFAIL;
1985         wake_up_interruptible_all(&dev->state_wait_q);
1986         return ret;
1987 }
1988
1989 int dsp_tdel(unsigned char minor)
1990 {
1991         struct taskdev *dev;
1992
1993         if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
1994                 printk(KERN_ERR
1995                        "omapdsp: no task device with minor %d\n", minor);
1996                 return -EINVAL;
1997         }
1998         spin_lock(&dev->state_lock);
1999         if (!(dev->state & OMAP_DSP_DEVSTATE_DELREQ)) {
2000                 printk(KERN_ERR
2001                        "omapdsp: taskdev %s is not requesting for tdel. "
2002                        "(state is %s)\n", dev->name, devstate_name(dev->state));
2003                 spin_unlock(&dev->state_lock);
2004                 return -EINVAL;
2005         }
2006         dev->state = OMAP_DSP_DEVSTATE_DELING;
2007         spin_unlock(&dev->state_lock);
2008
2009         return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_SAFE);
2010 }
2011
2012 int dsp_tkill(unsigned char minor)
2013 {
2014         struct taskdev *dev;
2015
2016         if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) {
2017                 printk(KERN_ERR
2018                        "omapdsp: no task device with minor %d\n", minor);
2019                 return -EINVAL;
2020         }
2021         spin_lock(&dev->state_lock);
2022         if (!(dev->state & OMAP_DSP_DEVSTATE_ATTACHED)) {
2023                 printk(KERN_ERR
2024                        "omapdsp: task has not been attached for taskdev %s\n",
2025                        dev->name);
2026                 spin_unlock(&dev->state_lock);
2027                 return -EINVAL;
2028         }
2029         dev->state = OMAP_DSP_DEVSTATE_KILLING;
2030         proclist_send_sigbus(&dev->proc_list);
2031         spin_unlock(&dev->state_lock);
2032
2033         return dsp_tdel_bh(minor, OMAP_DSP_MBCMD_TDEL_KILL);
2034 }
2035
2036 static int dsp_tdel_bh(unsigned char minor, unsigned short type)
2037 {
2038         struct taskdev *dev = taskdev[minor];
2039         struct dsptask *task;
2040         struct mbcmd mb;
2041         unsigned char tid, tid_response;
2042         int ret = minor;
2043
2044         task = dev->task;
2045         tid = task->tid;
2046         if (down_interruptible(&cfg_sem)) {
2047                 if (type == OMAP_DSP_MBCMD_TDEL_SAFE) {
2048                         dev->state = OMAP_DSP_DEVSTATE_DELREQ;
2049                         return -ERESTARTSYS;
2050                 } else {
2051                         tid_response = OMAP_DSP_TID_ANON;
2052                         ret = -ERESTARTSYS;
2053                         goto detach_out;
2054                 }
2055         }
2056         cfg_tid = OMAP_DSP_TID_ANON;
2057         cfg_cmd = MBCMD(TDEL);
2058         mbcmd_set(mb, MBCMD(TDEL), tid, type);
2059         dsp_mbcmd_send_and_wait(&mb, &cfg_wait_q);
2060         tid_response = cfg_tid;
2061         cfg_tid = OMAP_DSP_TID_ANON;
2062         cfg_cmd = 0;
2063         up(&cfg_sem);
2064
2065 detach_out:
2066         taskdev_detach_task(dev);
2067         dsp_task_unconfig(task);
2068         kfree(task);
2069
2070         if (tid_response != tid) {
2071                 printk(KERN_ERR "omapdsp: %s failed!\n",
2072                        (type == OMAP_DSP_MBCMD_TDEL_SAFE) ? "tdel" : "tkill");
2073                 ret = -EINVAL;
2074         }
2075         spin_lock(&dev->state_lock);
2076         dev->state = (dev->usecount > 0) ? OMAP_DSP_DEVSTATE_GARBAGE :
2077                                            OMAP_DSP_DEVSTATE_NOTASK;
2078         wake_up_interruptible_all(&dev->state_wait_q);
2079         spin_unlock(&dev->state_lock);
2080
2081         return ret;
2082 }
2083
2084 /*
2085  * state inquiry
2086  */
2087 long taskdev_state_stale(unsigned char minor)
2088 {
2089         if (taskdev[minor]) {
2090                 long state = taskdev[minor]->state;
2091                 taskdev[minor]->state |= OMAP_DSP_DEVSTATE_STALE;
2092                 return state;
2093         } else
2094                 return OMAP_DSP_DEVSTATE_NOTASK;
2095 }
2096
2097 /*
2098  * functions called from mailbox1 interrupt routine
2099  */
2100 void mbx1_wdsnd(struct mbcmd *mb)
2101 {
2102         unsigned char tid = mb->cmd_l;
2103         struct dsptask *task = dsptask[tid];
2104
2105         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2106                 printk(KERN_ERR "mbx: WDSND with illegal tid! %d\n", tid);
2107                 return;
2108         }
2109         if (sndtyp_bk(task->ttyp)) {
2110                 printk(KERN_ERR
2111                        "mbx: WDSND from block sending task! (task%d)\n", tid);
2112                 return;
2113         }
2114         if (sndtyp_psv(task->ttyp) &&
2115             !waitqueue_active(&task->dev->read_wait_q)) {
2116                 printk(KERN_WARNING
2117                        "mbx: WDSND from passive sending task (task%d) "
2118                        "without request!\n", tid);
2119                 return;
2120         }
2121
2122         write_word_to_fifo(&task->rcvdt.fifo, mb->data);
2123         wake_up_interruptible(&task->dev->read_wait_q);
2124 }
2125
2126 void mbx1_wdreq(struct mbcmd *mb)
2127 {
2128         unsigned char tid = mb->cmd_l;
2129         struct dsptask *task = dsptask[tid];
2130
2131         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2132                 printk(KERN_ERR "mbx: WDREQ with illegal tid! %d\n", tid);
2133                 return;
2134         }
2135         if (rcvtyp_psv(task->ttyp)) {
2136                 printk(KERN_ERR
2137                        "mbx: WDREQ from passive receiving task! (task%d)\n",
2138                        tid);
2139                 return;
2140         }
2141
2142         spin_lock(&task->wsz_lock);
2143         task->wsz = 2;
2144         spin_unlock(&task->wsz_lock);
2145         wake_up_interruptible(&task->dev->write_wait_q);
2146 }
2147
2148 void mbx1_bksnd(struct mbcmd *mb)
2149 {
2150         unsigned char tid = mb->cmd_l;
2151         unsigned short bid = mb->data;
2152         struct dsptask *task = dsptask[tid];
2153         unsigned short cnt;
2154
2155         if (bid >= ipbcfg.ln) {
2156                 printk(KERN_ERR "mbx: BKSND with illegal bid! %d\n", bid);
2157                 return;
2158         }
2159         ipb_bsycnt_dec(&ipbcfg);
2160         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2161                 printk(KERN_ERR "mbx: BKSND with illegal tid! %d\n", tid);
2162                 goto unuse_ipbuf_out;
2163         }
2164         if (sndtyp_wd(task->ttyp)) {
2165                 printk(KERN_ERR
2166                        "mbx: BKSND from word sending task! (task%d)\n", tid);
2167                 goto unuse_ipbuf_out;
2168         }
2169         if (sndtyp_pvt(task->ttyp)) {
2170                 printk(KERN_ERR
2171                        "mbx: BKSND from private sending task! (task%d)\n", tid);
2172                 goto unuse_ipbuf_out;
2173         }
2174         if (sync_with_dsp(&ipbuf[bid]->sd, tid, 10) < 0) {
2175                 printk(KERN_ERR "mbx: BKSND - IPBUF sync failed!\n");
2176                 return;
2177         }
2178
2179         /* should be done in DSP, but just in case. */
2180         ipbuf[bid]->next = OMAP_DSP_BID_NULL;
2181
2182         cnt = ipbuf[bid]->c;
2183         if (cnt > ipbcfg.lsz) {
2184                 printk(KERN_ERR "mbx: BKSND cnt(%d) > ipbuf line size(%d)!\n",
2185                        cnt, ipbcfg.lsz);
2186                 goto unuse_ipbuf_out;
2187         }
2188
2189         if (cnt == 0) {
2190                 /* 0-byte send from DSP */
2191                 unuse_ipbuf_nowait(bid);
2192                 goto done;
2193         }
2194         spin_lock(&task->rcvdt.bk.link.lock);
2195         ipblink_add_tail(&task->rcvdt.bk.link, bid, ipbuf);
2196         spin_unlock(&task->rcvdt.bk.link.lock);
2197         /* we keep coming bid and return alternative line to DSP. */
2198         balance_ipbuf();
2199
2200 done:
2201         wake_up_interruptible(&task->dev->read_wait_q);
2202         return;
2203
2204 unuse_ipbuf_out:
2205         unuse_ipbuf_nowait(bid);
2206         return;
2207 }
2208
2209 void mbx1_bkreq(struct mbcmd *mb)
2210 {
2211         unsigned char tid = mb->cmd_l;
2212         unsigned short cnt = mb->data;
2213         struct dsptask *task = dsptask[tid];
2214
2215         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2216                 printk(KERN_ERR "mbx: BKREQ with illegal tid! %d\n", tid);
2217                 return;
2218         }
2219         if (rcvtyp_wd(task->ttyp)) {
2220                 printk(KERN_ERR
2221                        "mbx: BKREQ from word receiving task! (task%d)\n", tid);
2222                 return;
2223         }
2224         if (rcvtyp_pvt(task->ttyp)) {
2225                 printk(KERN_ERR
2226                        "mbx: BKREQ from private receiving task! (task%d)\n",
2227                        tid);
2228                 return;
2229         }
2230         if (rcvtyp_psv(task->ttyp)) {
2231                 printk(KERN_ERR
2232                        "mbx: BKREQ from passive receiving task! (task%d)\n",
2233                        tid);
2234                 return;
2235         }
2236
2237         spin_lock(&task->wsz_lock);
2238         task->wsz = cnt*2;
2239         spin_unlock(&task->wsz_lock);
2240         wake_up_interruptible(&task->dev->write_wait_q);
2241 }
2242
2243 void mbx1_bkyld(struct mbcmd *mb)
2244 {
2245         unsigned short bid = mb->data;
2246
2247         if (bid >= ipbcfg.ln) {
2248                 printk(KERN_ERR "mbx: BKYLD with illegal bid! %d\n", bid);
2249                 return;
2250         }
2251
2252         /* should be done in DSP, but just in case. */
2253         ipbuf[bid]->next = OMAP_DSP_BID_NULL;
2254
2255         /* we don't need to sync with DSP */
2256         ipb_bsycnt_dec(&ipbcfg);
2257         release_ipbuf(bid);
2258 }
2259
2260 void mbx1_bksndp(struct mbcmd *mb)
2261 {
2262         unsigned char tid = mb->cmd_l;
2263         struct dsptask *task = dsptask[tid];
2264         struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk;
2265         struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r;
2266
2267         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2268                 printk(KERN_ERR "mbx: BKSNDP with illegal tid! %d\n", tid);
2269                 return;
2270         }
2271         if (sndtyp_wd(task->ttyp)) {
2272                 printk(KERN_ERR
2273                        "mbx: BKSNDP from word sending task! (task%d)\n", tid);
2274                 return;
2275         }
2276         if (sndtyp_gbl(task->ttyp)) {
2277                 printk(KERN_ERR
2278                        "mbx: BKSNDP from non-private sending task! (task%d)\n",
2279                        tid);
2280                 return;
2281         }
2282
2283         /*
2284          * we should not have delayed block at this point
2285          * because read() routine releases the lock of the buffer and
2286          * until then DSP can't send next data.
2287          */
2288
2289         if (sync_with_dsp(&ipbp->s, tid, 10) < 0) {
2290                 printk(KERN_ERR "mbx: BKSNDP - IPBUF sync failed!\n");
2291                 return;
2292         }
2293         printk(KERN_DEBUG "mbx: ipbuf_pvt_r->a = 0x%08lx\n",
2294                MKLONG(ipbp->ah, ipbp->al));
2295         spin_lock(&rcvdt->link.lock);
2296         ipblink_add_pvt(&rcvdt->link);
2297         spin_unlock(&rcvdt->link.lock);
2298         wake_up_interruptible(&task->dev->read_wait_q);
2299 }
2300
2301 void mbx1_bkreqp(struct mbcmd *mb)
2302 {
2303         unsigned char tid = mb->cmd_l;
2304         struct dsptask *task = dsptask[tid];
2305         struct ipbuf_p *ipbp = task->ipbuf_pvt_w;
2306
2307         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2308                 printk(KERN_ERR "mbx: BKREQP with illegal tid! %d\n", tid);
2309                 return;
2310         }
2311         if (rcvtyp_wd(task->ttyp)) {
2312                 printk(KERN_ERR
2313                        "mbx: BKREQP from word receiving task! (task%d)\n", tid);
2314                 return;
2315         }
2316         if (rcvtyp_gbl(task->ttyp)) {
2317                 printk(KERN_ERR
2318                        "mbx: BKREQP from non-private receiving task! (task%d)\n", tid);
2319                 return;
2320         }
2321         if (rcvtyp_psv(task->ttyp)) {
2322                 printk(KERN_ERR
2323                        "mbx: BKREQP from passive receiving task! (task%d)\n", tid);
2324                 return;
2325         }
2326
2327         if (sync_with_dsp(&ipbp->s, OMAP_DSP_TID_FREE, 10) < 0) {
2328                 printk(KERN_ERR "mbx: BKREQP - IPBUF sync failed!\n");
2329                 return;
2330         }
2331         printk(KERN_DEBUG "mbx: ipbuf_pvt_w->a = 0x%08lx\n",
2332                MKLONG(ipbp->ah, ipbp->al));
2333         spin_lock(&task->wsz_lock);
2334         task->wsz = ipbp->c*2;
2335         spin_unlock(&task->wsz_lock);
2336         wake_up_interruptible(&task->dev->write_wait_q);
2337 }
2338
2339 void mbx1_tctl(struct mbcmd *mb)
2340 {
2341         unsigned char tid = mb->cmd_l;
2342         struct dsptask *task = dsptask[tid];
2343
2344         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2345                 printk(KERN_ERR "mbx: TCTL with illegal tid! %d\n", tid);
2346                 return;
2347         }
2348
2349         if (!waitqueue_active(&task->dev->ioctl_wait_q)) {
2350                 printk(KERN_WARNING "mbx: unexpected TCTL from DSP!\n");
2351                 return;
2352         }
2353
2354         task->tctl_stat = mb->data;
2355         wake_up_interruptible(&task->dev->ioctl_wait_q);
2356 }
2357
2358 void mbx1_tcfg(struct mbcmd *mb)
2359 {
2360         unsigned char tid = mb->cmd_l;
2361         struct dsptask *task = dsptask[tid];
2362         unsigned short *tnm;
2363         volatile unsigned short *buf;
2364         int i;
2365
2366         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2367                 printk(KERN_ERR "mbx: TCFG with illegal tid! %d\n", tid);
2368                 return;
2369         }
2370         if ((task->state != TASK_STATE_CFGREQ) || (cfg_cmd != MBCMD(TCFG))) {
2371                 printk(KERN_WARNING "mbx: unexpected TCFG from DSP!\n");
2372                 return;
2373         }
2374
2375         if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
2376                 printk(KERN_ERR "mbx: TCFG - IPBUF sync failed!\n");
2377                 goto out;
2378         }
2379
2380         /*
2381          * read configuration data on system IPBUF
2382          */
2383         buf = ipbuf_sys_da->d;
2384         task->ttyp                 = buf[0];
2385         task->rcvdt.bk.ipbuf_pvt_r = MKVIRT(buf[1], buf[2]);
2386         task->ipbuf_pvt_w          = MKVIRT(buf[3], buf[4]);
2387         task->map_base             = MKVIRT(buf[5], buf[6]);
2388         task->map_length           = MKLONG(buf[7], buf[8]) << 1;       /* word -> byte */
2389         tnm                        = MKVIRT(buf[9], buf[10]);
2390         release_ipbuf_pvt(ipbuf_sys_da);
2391
2392         /*
2393          * copy task name string
2394          */
2395         if (dsp_address_validate(tnm, OMAP_DSP_TNM_LEN, "task name buffer") <0) {
2396                 task->name[0] = '\0';
2397                 goto out;
2398         }
2399
2400         for (i = 0; i < OMAP_DSP_TNM_LEN-1; i++) {
2401                 /* avoiding byte access */
2402                 unsigned short tmp = tnm[i];
2403                 task->name[i] = tmp & 0x00ff;
2404                 if (!tmp)
2405                         break;
2406         }
2407         task->name[OMAP_DSP_TNM_LEN-1] = '\0';
2408
2409         task->state = TASK_STATE_READY;
2410 out:
2411         wake_up_interruptible(&cfg_wait_q);
2412 }
2413
2414 void mbx1_tadd(struct mbcmd *mb)
2415 {
2416         unsigned char tid = mb->cmd_l;
2417
2418         if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TADD))) {
2419                 printk(KERN_WARNING "mbx: unexpected TADD from DSP!\n");
2420                 return;
2421         }
2422         cfg_tid = tid;
2423         wake_up_interruptible(&cfg_wait_q);
2424 }
2425
2426 void mbx1_tdel(struct mbcmd *mb)
2427 {
2428         unsigned char tid = mb->cmd_l;
2429
2430         if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBCMD(TDEL))) {
2431                 printk(KERN_WARNING "mbx: unexpected TDEL from DSP!\n");
2432                 return;
2433         }
2434         cfg_tid = tid;
2435         wake_up_interruptible(&cfg_wait_q);
2436 }
2437
2438 void mbx1_err_fatal(unsigned char tid)
2439 {
2440         struct dsptask *task = dsptask[tid];
2441
2442         if ((tid >= TASKDEV_MAX) || (task == NULL)) {
2443                 printk(KERN_ERR "mbx: FATAL ERR with illegal tid! %d\n", tid);
2444                 return;
2445         }
2446
2447         spin_lock(&task->dev->state_lock);
2448         proclist_send_sigbus(&task->dev->proc_list);
2449         spin_unlock(&task->dev->state_lock);
2450 }
2451
2452 static short *dbg_buf;
2453 static unsigned short dbg_buf_sz, dbg_line_sz;
2454 static int dbg_rp;
2455
2456 int dsp_dbg_config(short *buf, unsigned short sz, unsigned short lsz)
2457 {
2458 #ifdef OLD_BINARY_SUPPORT
2459         if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
2460                 dbg_buf = NULL;
2461                 dbg_buf_sz = 0;
2462                 dbg_line_sz = 0;
2463                 dbg_rp = 0;
2464                 return 0;
2465         }
2466 #endif
2467
2468         if (dsp_address_validate(buf, sz, "debug buffer") < 0)
2469                 return -1;
2470
2471         if (lsz > sz) {
2472                 printk(KERN_ERR
2473                        "omapdsp: dbg_buf lsz (%d) is greater than its "
2474                        "buffer size (%d)\n", lsz, sz);
2475                 return -1;
2476         }
2477
2478         dbg_buf = buf;
2479         dbg_buf_sz = sz;
2480         dbg_line_sz = lsz;
2481         dbg_rp = 0;
2482
2483         return 0;
2484 }
2485
2486 void dsp_dbg_stop(void)
2487 {
2488         dbg_buf = NULL;
2489 }
2490
2491 #ifdef OLD_BINARY_SUPPORT
2492 static void mbx1_dbg_old(struct mbcmd *mb);
2493 #endif
2494
2495 void mbx1_dbg(struct mbcmd *mb)
2496 {
2497         unsigned char tid = mb->cmd_l;
2498         int cnt = mb->data;
2499         char s[80], *s_end = &s[79], *p;
2500         unsigned short *src;
2501         int i;
2502
2503 #ifdef OLD_BINARY_SUPPORT
2504         if ((mbx_revision == MBREV_3_0) || (mbx_revision == MBREV_3_2)) {
2505                 mbx1_dbg_old(mb);
2506                 return;
2507         }
2508 #endif
2509
2510         if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
2511             (tid != OMAP_DSP_TID_ANON)) {
2512                 printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
2513                 return;
2514         }
2515         if (dbg_buf == NULL) {
2516                 printk(KERN_ERR "mbx: DBG command received, but "
2517                        "dbg_buf has not been configured yet.\n");
2518                 return;
2519         }
2520
2521         if (dsp_mem_enable(dbg_buf) < 0)
2522                 return;
2523
2524         src = &dbg_buf[dbg_rp];
2525         p = s;
2526         for (i = 0; i < cnt; i++) {
2527                 unsigned short tmp;
2528                 /*
2529                  * Be carefull that dbg_buf should not be read with
2530                  * 1-byte access since it might be placed in DARAM/SARAM
2531                  * and it can cause unexpected byteswap.
2532                  * For example,
2533                  *   *(p++) = *(src++) & 0xff;
2534                  * causes 1-byte access!
2535                  */
2536                 tmp = *src++;
2537                 *(p++) = tmp & 0xff;
2538                 if (*(p-1) == '\n') {
2539                         *p = '\0';
2540                         printk(KERN_INFO "%s", s);
2541                         p = s;
2542                         continue;
2543                 }
2544                 if (p == s_end) {
2545                         *p = '\0';
2546                         printk(KERN_INFO "%s\n", s);
2547                         p = s;
2548                         continue;
2549                 }
2550         }
2551         if (p > s) {
2552                 *p = '\0';
2553                 printk(KERN_INFO "%s\n", s);
2554         }
2555         if ((dbg_rp += cnt + 1) > dbg_buf_sz - dbg_line_sz)
2556                 dbg_rp = 0;
2557
2558         dsp_mem_disable(dbg_buf);
2559 }
2560
2561 #ifdef OLD_BINARY_SUPPORT
2562 static void mbx1_dbg_old(struct mbcmd *mb)
2563 {
2564         unsigned char tid = mb->cmd_l;
2565         char s[80], *s_end = &s[79], *p;
2566         unsigned short *src;
2567         volatile unsigned short *buf;
2568         int cnt;
2569         int i;
2570
2571         if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) &&
2572             (tid != OMAP_DSP_TID_ANON)) {
2573                 printk(KERN_ERR "mbx: DBG with illegal tid! %d\n", tid);
2574                 return;
2575         }
2576         if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) {
2577                 printk(KERN_ERR "mbx: DBG - IPBUF sync failed!\n");
2578                 return;
2579         }
2580         buf = ipbuf_sys_da->d;
2581         cnt = buf[0];
2582         src = MKVIRT(buf[1], buf[2]);
2583         if (dsp_address_validate(src, cnt, "dbg buffer") < 0)
2584                 return;
2585
2586         if (dsp_mem_enable(src) < 0)
2587                 return;
2588
2589         p = s;
2590         for (i = 0; i < cnt; i++) {
2591                 unsigned short tmp;
2592                 /*
2593                  * Be carefull that ipbuf should not be read with
2594                  * 1-byte access since it might be placed in DARAM/SARAM
2595                  * and it can cause unexpected byteswap.
2596                  * For example,
2597                  *   *(p++) = *(src++) & 0xff;
2598                  * causes 1-byte access!
2599                  */
2600                 tmp = *src++;
2601                 *(p++) = tmp & 0xff;
2602                 if (*(p-1) == '\n') {
2603                         *p = '\0';
2604                         printk(KERN_INFO "%s", s);
2605                         p = s;
2606                         continue;
2607                 }
2608                 if (p == s_end) {
2609                         *p = '\0';
2610                         printk(KERN_INFO "%s\n", s);
2611                         p = s;
2612                         continue;
2613                 }
2614         }
2615         if (p > s) {
2616                 *p = '\0';
2617                 printk(KERN_INFO "%s\n", s);
2618         }
2619
2620         release_ipbuf_pvt(ipbuf_sys_da);
2621         dsp_mem_disable(src);
2622 }
2623 #endif /* OLD_BINARY_SUPPORT */
2624
2625 /*
2626  * sysfs files
2627  */
2628 static ssize_t devname_show(struct device *d, struct device_attribute *attr,
2629                             char *buf)
2630 {
2631         struct taskdev *dev = to_taskdev(d);
2632         return sprintf(buf, "%s\n", dev->name);
2633 }
2634
2635 static ssize_t devstate_show(struct device *d, struct device_attribute *attr,
2636                              char *buf)
2637 {
2638         struct taskdev *dev = to_taskdev(d);
2639         return sprintf(buf, "%s\n", devstate_name(dev->state));
2640 }
2641
2642 static ssize_t proc_list_show(struct device *d, struct device_attribute *attr,
2643                               char *buf)
2644 {
2645         struct taskdev *dev;
2646         struct proc_list *pl;
2647         int len = 0;
2648
2649         dev = to_taskdev(d);
2650         spin_lock(&dev->state_lock);
2651         list_for_each_entry(pl, &dev->proc_list, list_head) {
2652                 len += sprintf(buf + len, "%d\n", pl->pid);
2653         }
2654         spin_unlock(&dev->state_lock);
2655
2656         return len;
2657 }
2658
2659 static ssize_t taskname_show(struct device *d, struct device_attribute *attr,
2660                              char *buf)
2661 {
2662         struct taskdev *dev = to_taskdev(d);
2663         int len;
2664
2665         len = sprintf(buf, "%s\n", dev->task->name);
2666
2667         return len;
2668 }
2669
2670 static ssize_t ttyp_show(struct device *d, struct device_attribute *attr,
2671                          char *buf)
2672 {
2673         unsigned short ttyp = to_taskdev(d)->task->ttyp;
2674         int len = 0;
2675
2676         len += sprintf(buf + len, "0x%04x\n", ttyp);
2677         len += sprintf(buf + len, "%s %s send\n",
2678                         (sndtyp_acv(ttyp)) ? "active" :
2679                                              "passive",
2680                         (sndtyp_wd(ttyp))  ? "word" :
2681                         (sndtyp_pvt(ttyp)) ? "private block" :
2682                                              "global block");
2683         len += sprintf(buf + len, "%s %s receive\n",
2684                         (rcvtyp_acv(ttyp)) ? "active" :
2685                                              "passive",
2686                         (rcvtyp_wd(ttyp))  ? "word" :
2687                         (rcvtyp_pvt(ttyp)) ? "private block" :
2688                                              "global block");
2689
2690         return len;
2691 }
2692
2693 static ssize_t fifosz_show(struct device *d, struct device_attribute *attr,
2694                            char *buf)
2695 {
2696         struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
2697         return sprintf(buf, "%d\n", fifo->sz);
2698 }
2699
2700 static int fifosz_store(struct device *d, struct device_attribute *attr,
2701                         const char *buf, size_t count)
2702 {
2703         struct dsptask *task = to_taskdev(d)->task;
2704         unsigned long fifosz;
2705         int ret;
2706
2707         fifosz = simple_strtol(buf, NULL, 10);
2708         ret = dsp_task_set_fifosz(task, fifosz);
2709
2710         return (ret < 0) ? ret : strlen(buf);
2711 }
2712
2713 static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr,
2714                             char *buf)
2715 {
2716         struct fifo_struct *fifo = &to_taskdev(d)->task->rcvdt.fifo;
2717         return sprintf(buf, "%d\n", fifo->cnt);
2718 }
2719
2720 static __inline__ char *bid_name(unsigned short bid)
2721 {
2722         static char s[6];
2723
2724         switch (bid) {
2725         case OMAP_DSP_BID_NULL:
2726                 return "NULL";
2727         case OMAP_DSP_BID_PVT:
2728                 return "PRIVATE";
2729         default:
2730                 sprintf(s, "%d", bid);
2731                 return s;
2732         }
2733 }
2734
2735 static ssize_t ipblink_show(struct device *d, struct device_attribute *attr,
2736                             char *buf)
2737 {
2738         struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->task->rcvdt.bk;
2739         int len;
2740
2741         spin_lock(&rcvdt->link.lock);
2742         len = sprintf(buf, "top  %s\ntail %s\n",
2743                       bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail));
2744         spin_unlock(&rcvdt->link.lock);
2745
2746         return len;
2747 }
2748
2749 static ssize_t wsz_show(struct device *d, struct device_attribute *attr,
2750                         char *buf)
2751 {
2752         return sprintf(buf, "%d\n", to_taskdev(d)->task->wsz);
2753 }
2754
2755 static ssize_t mmap_show(struct device *d, struct device_attribute *attr,
2756                          char *buf)
2757 {
2758         struct dsptask *task = to_taskdev(d)->task;
2759         return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length);
2760 }
2761
2762 /*
2763  * called from ipbuf_read_proc()
2764  */
2765 int ipbuf_is_held(unsigned char tid, unsigned short bid)
2766 {
2767         struct dsptask *task = dsptask[tid];
2768         unsigned short b;
2769         int ret = 0;
2770
2771         if (task == NULL)
2772                 return 0;
2773
2774         spin_lock(&task->rcvdt.bk.link.lock);
2775         ipblink_for_each(b, &task->rcvdt.bk.link, ipbuf) {
2776                 if (b == bid) { /* found */
2777                         ret = 1;
2778                         break;
2779                 }
2780         }
2781         spin_unlock(&task->rcvdt.bk.link.lock);
2782
2783         return ret;
2784 }
2785
2786 int __init dsp_taskmod_init(void)
2787 {
2788         int retval;
2789
2790         memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX);
2791         memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX);
2792
2793         retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask",
2794                                  &dsp_task_fops);
2795         if (retval < 0) {
2796                 printk(KERN_ERR
2797                        "omapdsp: failed to register task device: %d\n", retval);
2798                 return retval;
2799         }
2800
2801         bus_register(&dsptask_bus);
2802         retval = driver_register(&dsptask_driver);
2803         if (retval) {
2804                 printk(KERN_ERR
2805                        "omapdsp: failed to register DSP task driver: %d\n",
2806                        retval);
2807                 bus_unregister(&dsptask_bus);
2808                 unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
2809                 return -EINVAL;
2810         }
2811         dsp_task_class = class_create(THIS_MODULE, "dsptask");
2812
2813         return 0;
2814 }
2815
2816 void dsp_taskmod_exit(void)
2817 {
2818         class_destroy(dsp_task_class);
2819         driver_unregister(&dsptask_driver);
2820         bus_unregister(&dsptask_bus);
2821         unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");
2822 }