task.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,381 行 · 第 1/4 页
C
2,381 行
if (bid >= ipbcfg.ln) { printk(KERN_ERR "mailbox: BKYLD with illegal bid! %d\n", bid); return; } /* should be done in DSP, but just in case. */ ipbuf[bid]->next = OMAP_DSP_BID_NULL; /* we don't need to sync with DSP */ ipb_bsycnt_dec(&ipbcfg); release_ipbuf(bid);}void mailbox1_bksndp(unsigned char tid){ struct dsptask *task = dsptask[tid]; struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk; struct ipbuf_p *ipbp = rcvdt->ipbuf_pvt_r; if ((tid >= TASKDEV_MAX) || (task == NULL)) { printk(KERN_ERR "mailbox: BKSNDP with illegal tid! %d\n", tid); return; } if (sndtyp_wd(task->ttyp)) { printk(KERN_ERR "mailbox: BKSNDP from word sending task! " "(task%d)\n", tid); return; } if (sndtyp_gbl(task->ttyp)) { printk(KERN_ERR "mailbox: BKSNDP from non-private sending task! " "(task%d)\n", tid); return; } /* * we should not have delayed block at this point * because read() routine releases the lock of the buffer and * until then DSP can't send next data. */ if (sync_with_dsp(&ipbp->s, tid, 10) < 0) { printk(KERN_ERR "mailbox: BKSNDP - IPBUF sync failed!\n"); return; } printk(KERN_DEBUG "mailbox: ipbuf_pvt_r->a = 0x%08lx\n", MKLONG(ipbp->ah, ipbp->al)); ipblink_add_pvt(&rcvdt->link); wake_up_interruptible(&task->read_wait_q);}void mailbox1_bkreqp(unsigned char tid){ struct dsptask *task = dsptask[tid]; struct ipbuf_p *ipbp = task->ipbuf_pvt_w; if ((tid >= TASKDEV_MAX) || (task == NULL)) { printk(KERN_ERR "mailbox: BKREQP with illegal tid! %d\n", tid); return; } if (rcvtyp_wd(task->ttyp)) { printk(KERN_ERR "mailbox: BKREQP from word receiving task! " "(task%d)\n", tid); return; } if (rcvtyp_gbl(task->ttyp)) { printk(KERN_ERR "mailbox: BKREQP from non-private receiving task! " "(task%d)\n", tid); return; } if (rcvtyp_psv(task->ttyp)) { printk(KERN_ERR "mailbox: BKREQP from passive receiving task! " "(task%d)\n", tid); return; } if (sync_with_dsp(&ipbp->s, OMAP_DSP_TID_FREE, 10) < 0) { printk(KERN_ERR "mailbox: BKREQP - IPBUF sync failed!\n"); return; } printk(KERN_DEBUG "mailbox: ipbuf_pvt_w->a = 0x%08lx\n", MKLONG(ipbp->ah, ipbp->al)); task->wsz = ipbp->c*2; wake_up_interruptible(&task->write_wait_q);}void mailbox1_tctl(unsigned char tid, unsigned short data){ struct dsptask *task = dsptask[tid]; if ((tid >= TASKDEV_MAX) || (task == NULL)) { printk(KERN_ERR "mailbox: TCTL with illegal tid! %d\n", tid); return; } if (!waitqueue_active(&task->ioctl_wait_q)) { printk(KERN_WARNING "mailbox: unexpected TCTL from DSP!\n"); return; } task->tctl_stat = data; wake_up_interruptible(&task->ioctl_wait_q);}void mailbox1_tcfg(unsigned char tid, unsigned short data){ struct dsptask *task = dsptask[tid]; unsigned long tmp_ipbp_r, tmp_ipbp_w; unsigned long tmp_mapstart, tmp_maplen; unsigned long tmp_tnm; unsigned short *tnm; volatile unsigned short *buf; int i; if ((tid >= TASKDEV_MAX) || (task == NULL)) { printk(KERN_ERR "mailbox: TCFG with illegal tid! %d\n", tid); return; } if ((task->cfgstat != CFGSTAT_GOING) || tcfg_wait_cmd != MBCMD(TCFG)) { printk(KERN_WARNING "mailbox: unexpected TCFG from DSP!\n"); return; } if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) { printk(KERN_ERR "mailbox: TCFG - IPBUF sync failed!\n"); return; } /* * read configuration data on system IPBUF */ buf = ipbuf_sys_da->d; task->ttyp = buf[0]; tmp_ipbp_r = MKLONG(buf[1], buf[2]); tmp_ipbp_w = MKLONG(buf[3], buf[4]); tmp_mapstart = MKLONG(buf[5], buf[6]); tmp_maplen = MKLONG(buf[7], buf[8]); tmp_tnm = MKLONG(buf[9], buf[10]); task->rcvdt.bk.ipbuf_pvt_r = dspword_to_virt(tmp_ipbp_r); task->ipbuf_pvt_w = dspword_to_virt(tmp_ipbp_w); task->map_base = dspword_to_virt(tmp_mapstart); task->map_length = tmp_maplen << 1; /* word -> byte */ tnm = dspword_to_virt(tmp_tnm); for (i = 0; i < OMAP_DSP_TNM_LEN-1; i++) { /* avoiding byte access */ unsigned short tmp = tnm[i]; task->name[i] = tmp & 0x00ff; if (!tmp) break; } task->name[OMAP_DSP_TNM_LEN-1] = '\0'; release_ipbuf_pvt(ipbuf_sys_da); task->cfgstat = CFGSTAT_DONE; wake_up_interruptible(&tcfg_wait_q);}void mailbox1_tadd(unsigned char tid){ if (!waitqueue_active(&tcfg_wait_q) || tcfg_wait_cmd != MBCMD(TADD)) { printk(KERN_WARNING "mailbox: unexpected TADD from DSP!\n"); return; } tadd_tid = tid; wake_up_interruptible(&tcfg_wait_q);}void mailbox1_tdel(unsigned char tid){ if (!waitqueue_active(&tcfg_wait_q) || tcfg_wait_cmd != MBCMD(TDEL)) { printk(KERN_WARNING "mailbox: unexpected TDEL from DSP!\n"); return; } tdel_tid = tid; wake_up_interruptible(&tcfg_wait_q);}void mailbox1_err_fatal(unsigned char tid){ struct dsptask *task = dsptask[tid]; struct list_head *ptr; siginfo_t info; if ((tid >= TASKDEV_MAX) || (task == NULL)) { printk(KERN_ERR "mailbox: FATAL ERR with illegal tid! %d\n", tid); return; } info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = SI_KERNEL; info._sifields._sigfault._addr = NULL; list_for_each(ptr, &task->proc_list) { send_sig_info(SIGBUS, &info, ((struct proc_list *)ptr)->tsk); }}void mailbox1_dbg(unsigned char tid){ char s[64]; unsigned short *src; volatile unsigned short *buf; int cnt; int i, j; if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) && (tid != OMAP_DSP_TID_ANON)) { printk(KERN_ERR "mailbox: DBG with illegal tid! %d\n", tid); return; } if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) { printk(KERN_ERR "mailbox: DBG - IPBUF sync failed!\n"); return; } buf = ipbuf_sys_da->d; cnt = buf[0]; src = dspword_to_virt(MKLONG(buf[1], buf[2])); j = 0; for (i = 0; i < cnt; i++) { unsigned short tmp; /* * Be carefull that ipbuf should not be read with * 1-byte access since it might be placed in DARAM/SARAM * and it can cause unexpected byteswap. * For example, * s[j++] = *(src++) & 0xff; * causes 1-byte access! */ tmp = *src++; s[j++] = tmp & 0xff; if (s[j-1] == '\n') { s[j] = '\0'; printk(KERN_INFO "%s", s); j = 0; continue; } if (j == 63) { s[j] = '\0'; printk(KERN_INFO "%s\n", s); j = 0; continue; } } if (j > 0) { s[j] = '\0'; printk(KERN_INFO "%s\n", s); } release_ipbuf_pvt(ipbuf_sys_da);}#ifdef CONFIG_PROC_FS/* * proc file entry */#define openstat_name(stat) (\ ((stat) == OMAP_DSP_OPENSTAT_CLOSE) ? "CLOSE" :\ ((stat) == OMAP_DSP_OPENSTAT_OPEN) ? "OPEN" :\ ((stat) == OMAP_DSP_OPENSTAT_REQ) ? "REQ" :\ "unknown")#define cfgstat_name(stat) (\ ((stat) == CFGSTAT_ERR) ? "ERR" :\ ((stat) == CFGSTAT_GOING) ? "GOING" :\ ((stat) == CFGSTAT_DONE) ? "DONE" :\ ((stat) == CFGSTAT_ABORT) ? "ABORT" :\ "unknown")static inline char *bid_name(unsigned short bid){ static char s[6]; switch (bid) { case OMAP_DSP_BID_NULL: return "NULL"; case OMAP_DSP_BID_PVT: return "PRIVATE"; default: sprintf(s, "%d", bid); return s; }}static inline char *sndtyp_name(unsigned short ttyp){ static char s[32]; sprintf(s, "%s %s send", (sndtyp_acv(ttyp)) ? "active" : "passive", (sndtyp_wd(ttyp)) ? "word" : (sndtyp_pvt(ttyp)) ? "private block" : "global block"); return s;}static inline char *rcvtyp_name(unsigned short ttyp){ static char s[32]; sprintf(s, "%s %s receive", (rcvtyp_acv(ttyp)) ? "active" : "passive", (rcvtyp_wd(ttyp)) ? "word" : (rcvtyp_pvt(ttyp)) ? "private block" : "global block"); return s;}static int omap_dsp_proc_taskdev_stat_read(char *page, char **start, off_t off, int count, int *eof, void *data){ struct taskdev *dev; struct dsptask *task; struct list_head *ptr; char *out; int len; preempt_disable(); dev = (struct taskdev *)data; task = dev->task; out = page; out += sprintf(out, "device name: %s\n" "openstat %s\n", dev->name, openstat_name(dev->openstat)); if (task) { unsigned short ttyp = task->ttyp; out += sprintf(out, " attached task: %s\n" " cfgstat %s\n" " tid %d\n" " ttyp 0x%04x (%s, %s)\n", task->name, cfgstat_name(task->cfgstat), task->tid, ttyp, sndtyp_name(ttyp), rcvtyp_name(ttyp)); if (sndtyp_wd(ttyp)) { struct fifo_struct *fifo = &task->rcvdt.fifo; out += sprintf(out, " fifo->buf 0x%p\n" " fifo->sz %d\n" " fifo->cnt %d\n" " fifo->wp %d\n", fifo->buf, fifo->sz, fifo->cnt, fifo->wp); } else { /* sndtyp_bk */ struct rcvdt_bk_struct *rcvdt = &task->rcvdt.bk; out += sprintf(out, " delayed list top %s\n" " tail %s\n", bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail)); if (sndtyp_pvt(ttyp)) { out += sprintf(out, " private IPBUF for read 0x%p\n", rcvdt->ipbuf_pvt_r); } } out += sprintf(out, " wsz %d\n", task->wsz); if (rcvtyp_pvt(ttyp)) { out += sprintf(out, " private IPBUF for write 0x%p\n", task->ipbuf_pvt_w); } if (task->map_length) { out += sprintf(out, " map_base %p\n" " map_length %d\n", task->map_base, task->map_length); } out += sprintf(out, " user pid "); list_for_each(ptr, &task->proc_list) { out += sprintf(out, " %d", ((struct proc_list *)ptr)->tsk->pid); } out += sprintf(out, "\n"); } else { out += sprintf(out, "task not attached.\n"); } preempt_enable(); len = out - page; len -= off; if (len < count) { *eof = 1; if (len <= 0) return 0; } else { len = count; } *start = page + off; return len;}static int omap_dsp_proc_taskdev_fifosz_read(char *page, char **start, off_t off, int count, int *eof, void *data){ struct taskdev *dev; struct dsptask *task; size_t fifosz; int len; dev = (struct taskdev *)data; task = dev->task; fifosz = (task && sndtyp_wd(task->ttyp)) ? task->rcvdt.fifo.sz : 0; len = sprintf(page, "%d\n", fifosz); return len;}static int omap_dsp_proc_taskdev_fifosz_write(struct file *file, const char *buffer, unsigned long count, void *data){ struct taskdev *dev; struct dsptask *task; int len; char tmp[16]; unsigned long fifosz; int ret; dev = (struct taskdev *)data; task = dev->task; if (task == NULL) { printk(KERN_ERR "task not attached.\n"); return -EINVAL; } len = (count > 15) ? 15 : count; if (copy_from_user(tmp, buffer, len)) return -EFAULT; tmp[len] = '\0'; fifosz = simple_strtol(tmp, NULL, 10); if ((ret = omap_dsp_task_set_fifosz(task, fifosz)) < 0) return ret; return len;}/* * called from omap_dsp_proc_ipbuf_read() */int omap_dsp_ipbuf_held(unsigned char tid, unsigned short bid){ struct dsptask *task = dsptask[tid]; unsigned short b; int ret = 0; if (task == NULL) return 0; disable_irq(INT_D2A_MB1); ipblink_for_each(b, &task->rcvdt.bk.link, ipbuf) { if (b == bid) { /* found */ ret = 1; break; } } enable_irq(INT_D2A_MB1); return ret;}static void omap_dsp_taskdev_create_proc(struct taskdev *dev){ struct proc_dir_entry *ent; if (procdir_dsptask == NULL) return; dev->procent_dir = proc_mkdir(dev->name, procdir_dsptask); if (dev->procent_dir == NULL) { printk(KERN_ERR "omapdsp: failed to register proc directory: " "%s\n", dev->name); return; } ent = create_proc_read_entry("status", 0, dev->procent_dir, omap_dsp_proc_taskdev_stat_read, dev); if (ent == NULL) { printk(KERN_ERR "omapdsp: failed to register " "status proc device for: %s\n", dev->name); return; } ent = create_proc_entry("fifosz", S_IFREG | S_IWUGO | S_IRUGO, dev->procent_dir); if (ent == NULL) { printk(KERN_ERR "omapdsp: failed to register fifosz " "proc device for: %s\n", dev->name); return; } ent->read_proc = omap_dsp_proc_taskdev_fifosz_read; ent->write_proc = omap_dsp_proc_taskdev_fifosz_write; ent->data = dev;}static void omap_dsp_taskdev_remove_proc(struct taskdev *dev){ if (dev->procent_dir == NULL) return; remove_proc_entry("status", dev->procent_dir); remove_proc_entry("fifosz", dev->procent_dir); remove_proc_entry(dev->name, procdir_dsptask); dev->procent_dir = NULL;}void __init omap_dsp_taskdev_create_procdir(void){ procdir_dsptask = proc_mkdir("task", procdir_dsp); if (procdir_dsptask == NULL) { printk(KERN_ERR "omapdsp: failed to register proc device: " "dsp/task\n"); }}void omap_dsp_taskdev_remove_procdir(void){ if (procdir_dsptask == NULL) return; remove_proc_entry("task", procdir_dsp); procdir_dsptask = NULL;}#endif /* CONFIG_PROC_FS */int __init omap_dsp_taskmod_init(void){ int retval; taskmod_cfgstat = CFGSTAT_ERR; init_waitqueue_head(&tcfg_wait_q); memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX); memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX); retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask", &omap_dsp_task_fops); if (retval < 0) { printk(KERN_ERR "omapdsp: failed to register task device: %d\n", retval); return retval; } devfs_mk_dir("dsptask");#ifdef CONFIG_PROC_FS omap_dsp_taskdev_create_procdir();#endif return 0;}void omap_dsp_taskmod_exit(void){ devfs_remove("dsptask"); unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask");#ifdef CONFIG_PROC_FS omap_dsp_taskdev_remove_procdir();#endif}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?