dspctl.c

来自「Omap5910 上实现双核通信 DSP GateWay」· C语言 代码 · 共 1,167 行 · 第 1/2 页

C
1,167
字号
/* * dspapps/utils/dspctl.c * * control utility for DSP Gateway * * Copyright (C) 2002-2005 Nokia Corporation * * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 2005/06/02:  DSP Gateway version 3.3 */#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <fcntl.h>#include <asm/arch/dsp.h>#include "dspctl.h"enum regspace { SPACE_MEM, SPACE_IO };struct ctlcmd {	char *name;	int argc;	int (*f)(char **argv);};static void usage(char *cmd);static void driver_version_check(void);static int do_start(char **argv);static int do_stop(char **argv);static int do_version(char **argv);static int do_load(char **argv);static int do_run(char **argv);static int do_reset(char **argv);static int do_cleanup(char **argv);static int do_setrstvect(char **argv);static int do_gbl_idle(char **argv);static int do_cpu_idle(char **argv);static int do_suspend(char **argv);static int do_resume(char **argv);static int do_dspcfg(char **argv);static int do_dspuncfg(char **argv);static int do_poll(char **argv);static int do_kmem_reserve(char **argv);static int do_kmem_release(char **argv);static int do_exmap(char **argv);static int do_exunmap(char **argv);static int do_mapflush(char **argv);static int do_fbexport(char **argv);static int do_mmuinit(char **argv);static int do_mmuitack(char **argv);static int do_mkdev(char **argv);static int do_rmdev(char **argv);static int do_tadd(char **argv);static int do_tdel(char **argv);static int do_getvar(char **argv);static int do_setvar_1(char **argv);static int do_regread(char **argv);static int do_regread_io(char **argv);static int __regread(enum regspace space, unsigned short adr);static int do_regwrite(char **argv);static int do_regwrite_io(char **argv);static int __regwrite(enum regspace space, unsigned short adr, unsigned short val);static int do_runlevel(char **argv);static int do_mbsend(char **argv);static int do_showmyprintk(char **argv);static int do_setuart(char **argv);static int do_display(char **argv);static void usage(char *cmd){	fprintf(stderr, "dspctl version %s\n\n", VERSION_STR);	fprintf(stderr, "usage: %s <command> ...\n", cmd);	fprintf(stderr, "  command:\n"		"    start <cofffile>\n"		"    stop\n"		"\n"		"    version <cofffile>\n"		"    load <cofffile>\n"		"    run (=unreset)\n"		"    reset\n"		"    cleanup\n"		"    setrstvect <addr>\n"		"    gbl_idle\n"		"    cpu_idle\n"		"    suspend\n"		"    resume\n"		"    dspcfg\n"		"    dspuncfg\n"		"    poll\n"		"    kmem_reserve <request size>\n"		"    kmem_release\n"		"    exmap <dspadr> <request size>\n"		"    exunmap <dspadr>\n"		"    mapflush\n"		"    fbexport <dspadr>\n"		"    mmuinit\n"		"    mmuitack\n"		"    mkdev <devname>\n"		"    rmdev <devname>\n"		"    tadd <minor> <addr>\n"		"    tdel <minor>\n"		"    getvar <varid>\n"		"    setvar <varid> <data>\n"		"    regread [-io] <adr>\n"		"    regwrite [-io] <adr> <val>\n"		"    runlevel <user|super>\n"		"    mbsend <cmd> <data>\n"		"    setuart \n");}static struct ctlcmd ctlcmd[] = {	{ "start",        3, do_start },	{ "stop",         2, do_stop },	{ "version",      3, do_version },	{ "load",         3, do_load },	{ "run",          2, do_run },	{ "unreset",      2, do_run },	{ "reset",        2, do_reset },	{ "cleanup",      2, do_cleanup },	{ "setrstvect",   3, do_setrstvect },	{ "gbl_idle",     2, do_gbl_idle },	{ "cpu_idle",     2, do_cpu_idle },	{ "suspend",      2, do_suspend },	{ "resume",       2, do_resume },	{ "dspcfg",       2, do_dspcfg },	{ "dspuncfg",     2, do_dspuncfg },	{ "poll",         2, do_poll },	{ "kmem_reserve", 3, do_kmem_reserve },	{ "kmem_release", 2, do_kmem_release },	{ "exmap",        4, do_exmap },	{ "exunmap",      3, do_exunmap },	{ "mapflush",     2, do_mapflush },	{ "fbexport",     3, do_fbexport },	{ "mmuinit",      2, do_mmuinit },	{ "mmuitack",     2, do_mmuitack },	{ "mkdev",        3, do_mkdev },	{ "rmdev",        3, do_rmdev },	{ "tadd",         4, do_tadd },	{ "tdel",         3, do_tdel },	{ "getvar",       3, do_getvar },	{ "setvar",       4, do_setvar_1 },	{ "regread",      3, do_regread },	{ "regread",      4, do_regread_io },	{ "regwrite",     4, do_regwrite },	{ "regwrite",     5, do_regwrite_io },	{ "runlevel",     3, do_runlevel },	{ "mbsend",       4, do_mbsend },	{ "showmyprintk", 2, do_showmyprintk},	{ "setuart",      2, do_setuart},        { "display",      2, do_display },	{ NULL, 0, NULL },};static int do_showmyprintk( char **argv){        int fd;	        if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {	  perror("open control device");	  return 1;        }	printf("Myprintkbuf: \n");        ioctl(fd, OMAP_DSP_IOCT_SHOWMYPRINTK);	close(fd);	return 0;}   static int do_setuart( char **argv){        int fd;        if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {          perror("open control device");          return 1;        }        printf("To switch uart: \n");        ioctl(fd, OMAP_DSP_IOCT_SETUART);        close(fd);	printf("ioctl over\n");        return 0;}static int do_display(char **argv){        int fd;	if ((fd = open(DSPMEMDEVNM, O_RDWR)) < 0) {	   perror("open dspmem device");	   return 1;	}	printf("DSP display\n");	ioctl(fd, OMAP_DSP_MEM_IOCTL_DISPLAY, NULL);	close(fd);	return 0;}int main(int argc, char **argv){	struct ctlcmd *cmd;	if (argc < 2) {		usage(argv[0]);		return 1;	}		/* driver version chck */	driver_version_check();	/* uniformed functions */	for (cmd = &ctlcmd[0]; cmd->name; cmd++) {		if (!strcmp(argv[1], cmd->name) && (argc == cmd->argc))			return cmd->f(argv);	}	usage(argv[0]);	return 1;}static void driver_version_check(void){	int fd;	char *fn1 = "/sys/devices/platform/dsp.0/ifver";	char *fn2 = "/sys/devices/platform/dsp0/ifver";	char *fn3 = "/sys/devices/platform/dsp/ifver";	char buf[4096];	char *s, *p;	int cnt;	if (((fd = open(fn1, O_RDONLY)) < 0) &&	    ((fd = open(fn2, O_RDONLY)) < 0) &&	    ((fd = open(fn3, O_RDONLY)) < 0)) {		fprintf(stderr,			"Warning: none of %s, %s or %s is found.\n"			"(DSP Gateway driver is too old or not loaded)\n",			fn1, fn2, fn3);		sleep(1);		return;	}	cnt = read(fd, buf, 4096);	close(fd);	if (cnt < 0)		goto fail;	buf[cnt] = '\0';	for (s = buf; s < buf + cnt; s = p + 1) {		for (p = s; *p && (*p != '\n'); p++);		if (!strncmp(s, IFVER_STR, p-s))			return;	/* success */	}fail:	fprintf(stderr,"***************************************************************\n""Warning: versions of dspctl and DSP Gateway driver don't match!\n""  dspctl version: %s\n""  driver supported I/F version:\n""%s""***************************************************************\n\n",		IFVER_STR, buf);	sleep(1);}static int dsptask_dir_check(void){	struct stat dir_stat;	if (stat(TASKDEV_DIR, &dir_stat) < 0) {		if (mkdir(TASKDEV_DIR, 0755) < 0) {			perror("mkdev " TASKDEV_DIR);			return 1;		}	} else {		if (!S_ISDIR(dir_stat.st_mode)) {			fprintf(stderr, TASKDEV_DIR " is not a directory.\n");			return 1;		}	}	return 0;}static int dev_mklink(int n){	int fd;	int i;	char name[OMAP_DSP_TNM_LEN];	char path1[20];	char path2[20 + OMAP_DSP_TNM_LEN];	for (i = 0; i < n; i++) {		int retry = 5;		sprintf(path1, "/dev/dsptask%d", i);#if 0 // 3.1		if ((fd = open(path1, O_RDWR)) < 0)			/* dynamic device file system (devfs, udev) */			continue;#elseretry:		if ((fd = open(path1, O_RDWR)) < 0) {			/* wait for udevd creates the node */			if (--retry) {				sleep(1);				goto retry;			}			perror("open taskdev");			return 1;		}#endif		if (ioctl(fd, OMAP_DSP_TASK_IOCTL_GETNAME, name) < 0) {			perror("GETNAME");			return 1;		}		close(fd);		sprintf(path2, TASKDEV_DIR "/%s", name);		if (symlink(path1, path2) < 0) {			perror("symlink");			return 1;		}	}	return 0;}static int dev_unlink(int n){	int fd;	int i;	int ret = 0;	char name[OMAP_DSP_TNM_LEN];	char path1[20];	char path2[20 + OMAP_DSP_TNM_LEN];	for (i = 0; i < n; i++) {		sprintf(path1, "/dev/dsptask%d", i);		if ((fd = open(path1, O_RDWR)) < 0)			/* dynamic device file system (devfs, udev) */			continue;		if (ioctl(fd, OMAP_DSP_TASK_IOCTL_GETNAME, name) < 0) {			perror("GETNAME");			ret = 1;			continue;		}		close(fd);		sprintf(path2, TASKDEV_DIR "/%s", name);		if (unlink(path2) < 0) {			perror("unlink");			ret = 1;			continue;		}	}	return ret;}static int do_start(char **argv){	int fd;	int ret;	int n_task;	if ((ret = dsptask_dir_check()) != 0)		return ret;	if ((ret = do_load(argv)) != 0)		return ret;	if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {		perror("open control device");		return 1;	}	printf("releasing DSP reset\n");	ioctl(fd, OMAP_DSP_IOCTL_RUN);	usleep(10000);	/* wait for DSP initialization */	printf("DSP configuration ... ");	if (ioctl(fd, OMAP_DSP_IOCTL_DSPCFG) < 0) {		printf("failed\n");		perror("");		return 1;	}	printf("succeeded\n");	if ((n_task = ioctl(fd, OMAP_DSP_IOCTL_TASKCNT)) < 0) {		perror("TASKCNT");		return 1;	}	close(fd);	return dev_mklink(n_task);}static int do_stop(char **argv){	int fd;	int n_task;	int ret = 0;	if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {		perror("open control device");		return 1;	}	if ((n_task = ioctl(fd, OMAP_DSP_IOCTL_TASKCNT)) < 0) {		perror("TASKCNT");		return 1;	}	ret = dev_unlink(n_task);	printf("releasing resources for DSP\n");	ioctl(fd, OMAP_DSP_IOCTL_DSPUNCFG);	printf("DSP reset\n");	ioctl(fd, OMAP_DSP_IOCTL_RESET);	close(fd);	return ret;}static int do_version(char **argv){	char *coffname = argv[2];	struct dspgw_version version;	if (strcmp(&coffname[strlen(coffname)-4], ".out")) {		fprintf(stderr, "cofffile name must be *.out!\n");		return 1;	}	if (read_dspgw_version(&version, coffname) < 0)		printf("DSP Gateway binary version 3.1 or before.\n");	else		printf("DSP Gateway binary version %d.%d.%d.%d\n",		       version.major, version.minor,		       version.extra1, version.extra2);	return 0;}static int do_load(char **argv){	char *coffname = argv[2];	unsigned long resetvect_adr;	int ctl_fd;	if (strcmp(&coffname[strlen(coffname)-4], ".out")) {		fprintf(stderr, "cofffile name must be *.out!\n");		return 1;	}	ctl_fd = open(CTLDEVNM, O_RDWR);	if (ctl_fd < 0) {		perror("open control device");		return 1;	}	/*	 * Theoretically this is not needed because kernel sets	 * no byte-swapping mode, but it is reported that	 * in OMAP1510, DSP MMU fault happens without this operation.	 */	ioctl(ctl_fd, OMAP_DSP_IOCTL_MPUI_BYTESWAP_OFF);	printf("loading %s...\n", coffname);	resetvect_adr = load_coff(coffname);	if (resetvect_adr > 0x00ffffff) {		fprintf(stderr, "Can't determine reset vector address\n");		return 1;	}	usleep(10000);	/* wait for DSP memory settled */	ioctl(ctl_fd, OMAP_DSP_IOCTL_RESET);	printf("setting DSP reset vector to 0x%06lx\n", resetvect_adr);	ioctl(ctl_fd, OMAP_DSP_IOCTL_SETRSTVECT, resetvect_adr);	close(ctl_fd);	return 0;}static int do_run(char **argv){	int fd;	if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {		perror("open control device");		return 1;	}	printf("releasing DSP reset\n");	ioctl(fd, OMAP_DSP_IOCTL_RUN);	close(fd);	return 0;}static int do_reset(char **argv){	int fd;	if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {		perror("open control device");		return 1;	}	printf("DSP reset\n");	ioctl(fd, OMAP_DSP_IOCTL_RESET);	close(fd);	return 0;}static int do_cleanup(char **argv){	int fd_ctl, fd_mem;	int n_task;	if ((fd_ctl = open(CTLDEVNM, O_RDWR)) < 0) {		perror("open control device");		return 1;	}	if ((n_task = ioctl(fd_ctl, OMAP_DSP_IOCTL_TASKCNT)) < 0)		perror("TASKCNT");	else		dev_unlink(n_task);	/* ignoring the result */	printf("releasing resources for DSP\n");	ioctl(fd_ctl, OMAP_DSP_IOCTL_DSPUNCFG);	printf("DSP reset\n");	ioctl(fd_ctl, OMAP_DSP_IOCTL_RESET);	close(fd_ctl);	if ((fd_mem = open(DSPMEMDEVNM, O_RDWR)) < 0) {		perror("open dspmem device");		return 1;	}	printf("flush DSP TLB.\n");	ioctl(fd_mem, OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH);	printf("initialize DSP MMU.\n");	ioctl(fd_mem, OMAP_DSP_MEM_IOCTL_MMUINIT);	close(fd_mem);	return 0;}static int do_setrstvect(char **argv){	int fd;	unsigned long adr = strtoul(argv[2], NULL, 16);	if ((fd = open(CTLDEVNM, O_RDWR)) < 0) {		perror("open control device");		return 1;	}	printf("setting DSP reset vector to 0x%06lx\n", adr);	ioctl(fd, OMAP_DSP_IOCTL_SETRSTVECT, adr);	close(fd);	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?