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 + -
显示快捷键?