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