📄 dld_server.c
字号:
return 0;}static int server_dspunconfig(int fd){ int cfd; int n_task; int status = 0; if ((cfd = open(DEVNAME_CONTROL, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } if ((n_task = ioctl(fd, OMAP_DSP_IOCTL_TASKCNT)) < 0) { prmsg("TASKCNT failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); status = -1; } else status = dev_unlink(n_task); prmsg("releasing resources for DSP\n"); ioctl(cfd, OMAP_DSP_IOCTL_DSPUNCFG); close(cfd); if (status < 0) sendback_event(fd, DLD_EVENT_ERROR); else sendback_event(fd, DLD_EVENT_DONE); return 0;}static int server_suspend(int fd){ int cfd; int ret; if ((cfd = open(DEVNAME_CONTROL, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("suspending DSP\n"); ret = ioctl(cfd, OMAP_DSP_IOCTL_SUSPEND); close(cfd); if (ret < 0) { prmsg("SUSPEND failed\n"); sendback_event(fd, DLD_EVENT_ERROR); return 1; } sendback_event(fd, DLD_EVENT_DONE); suspend = 1; return 0;}static int server_resume(int fd){ int cfd; int ret; suspend = 0; if ((cfd = open(DEVNAME_CONTROL, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("resuming DSP\n"); ret = ioctl(cfd, OMAP_DSP_IOCTL_RESUME); close(cfd); if (ret < 0) { prmsg("RESUME failed\n"); sendback_event(fd, DLD_EVENT_ERROR); return 1; } sendback_event(fd, DLD_EVENT_DONE); return 0;}static int server_exmap(int fd, struct server_event *e){ struct omap_dsp_mapinfo mapinfo = { e->data.exmap.dspadr, e->data.exmap.size }; int ret; int cfd; if ((cfd = open(DEVNAME_DSPMEM, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("mapping external memory for DSP: " "dspadr = 0x%06lx, size = 0x%lx\n", mapinfo.dspadr, mapinfo.size); ret = ioctl(cfd, OMAP_DSP_MEM_IOCTL_EXMAP, &mapinfo); close(cfd); if (ret < 0) { prmsg("EXMAP failed\n"); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("%d bytes mapped.\n", ret); sendback_event(fd, DLD_EVENT_DONE); return 0;}static int server_mmuinit(int fd){ int cfd; if ((cfd = open(DEVNAME_DSPMEM, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("DSP MMU initialize.\n"); ioctl(cfd, OMAP_DSP_MEM_IOCTL_MMUINIT); close(cfd); sendback_event(fd, DLD_EVENT_DONE); return 0;}static int server_mapflush(int fd){ int cfd; if ((cfd = open(DEVNAME_DSPMEM, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("DSP TLB has been flushed.\n"); ioctl(cfd, OMAP_DSP_MEM_IOCTL_EXMAP_FLUSH); close(cfd); sendback_event(fd, DLD_EVENT_DONE); return 0;}static int server_mbsend(int fd, struct server_event *e){ struct omap_dsp_mailbox_cmd mbcmd = { e->data.mbsend.cmd, e->data.mbsend.data }; int cfd; if ((cfd = open(DEVNAME_CONTROL, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); sendback_event(fd, DLD_EVENT_ERROR); return 1; } prmsg("sending mailbox command to DSP: cmd = 0x%02x, data = 0x%02x\n", mbcmd.cmd, mbcmd.data); ioctl(cfd, OMAP_DSP_IOCTL_MBSEND, &mbcmd); close(cfd); sendback_event(fd, DLD_EVENT_DONE); return 0;}#endif /* DSP_EMULATION */#ifndef DSP_EMULATION/* * */int twch_tadd(struct taskent *te){ u32 taskadr; pid_t pid;#ifdef USE_FORK if (te->cobj->request_lock++) { prmsg("device %s is locked. delaying TADD request.\n", te->devname); return 0; }#endif /* * clear request so that the server detect next request. */ te->request = TREQ_NONE; prmsg("starting TADD process for device %s.\n", te->devname); taskadr = task_load(te); pid = fork_task_add(te->minor, taskadr); if (pid < 0) exit(1);#ifdef USE_FORK if (pid == 0) /* child */ exit(0);#endif /* parent */ if (taskadr == OMAP_DSP_TADD_ABORTADR) return 1; return 0;}int twch_tdel(struct taskent *te){ pid_t pid;#ifdef USE_FORK if (te->cobj->request_lock++) { prmsg("device %s is locked. delaying TDEL request.\n", te->devname); return 0; }#endif /* * clear request so that the server detect next request. */ te->request = TREQ_NONE; prmsg("starting TDEL process for device %s.\n", te->devname); pid = fork_task_del(te->minor); if (pid < 0) exit(1);#ifdef USE_FORK if (pid == 0) { /* child */ /* * task_clear() will be done when * the server received TDEL_DONE event. */ exit(0); } /* parent */ return 0;#else return task_clear(te);#endif}static int read_twch(void){ long tstat[TID_MAX]; struct taskent *te; size_t cnt; int devcnt; int i; if ((cnt = read(server_fds.fd_twch, tstat, TID_MAX * sizeof(long))) < 0) { prmsg("read from dsptwch failed\n"); return -1; } devcnt = cnt / 4; prmsg("dsp_dld: event detected.\n"); for (i = 0; i < devcnt; i++) { if ((te = taskent_find_by_minor(i)) == NULL) continue; switch (tstat[i]) { /* if STALE bit is set, it means the request has * accepted already, and we ignore it. */ case OMAP_DSP_DEVSTATE_ADDREQ: prmsg("device %s is requesting for TADD.\n", te->devname); te->request = TREQ_ADD; break; case OMAP_DSP_DEVSTATE_DELREQ: prmsg("device %s is requesting for TDEL.\n", te->devname); te->request = TREQ_DEL; break; } } memcpy(tstat_prev, tstat, devcnt * sizeof(long)); return taskent_process_request_all();}static server_return_t read_errdt(int fd){ unsigned long errcode; size_t cnt; if ((cnt = read(fd, &errcode, 4)) < 0) { prmsg("read from dsperr failed\n"); return SERVER_RESTART; } prmsg("dsp_dld: DSP error detected.\n"); if (errcode & OMAP_DSP_ERRDT_WDT) { prmsg(" DSP watchdog timer expired.\n" " (some tasks may be in busy loop)\n"); return SERVER_RESTART; } if (errcode & OMAP_DSP_ERRDT_MMU) {#if 0 // recovery int fd_dspmem; prmsg(" DSP MMU fault. trying to recover...\n"); if ((fd_dspmem = open(DEVNAME_DSPMEM, O_RDWR)) < 0) { prmsg("%s open failed\n", DEVNAME_DSPMEM); return SERVER_RESTART; } ioctl(fd_dspmem, OMAP_DSP_MEM_IOCTL_MMUITACK); close(fd_dspmem);#else prmsg(" DSP MMU fault.\n"); return SERVER_RESTART;#endif } return SERVER_OK;}#endif /* !DSP_EMULATION */static int server_open(char *name){ int fd; struct sockaddr_un addr; if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { prmsg("socket() failed at %s line %d\n", __FILE__, __LINE__); return -1; } if (!access(name, F_OK)) unlink(name); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, name); if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { prmsg("bind() failed at %s line %d\n", __FILE__, __LINE__); return -1; } if (listen(fd, 1) < 0) { prmsg("listen() failed at %s line %d\n", __FILE__, __LINE__); return -1; } return fd;}static int server_close(int fd, char *name){ close(fd); unlink(name); return 0;}static int server_accept(int fd){ int fd_acc; struct sockaddr_un addr; int len = sizeof(struct sockaddr_un); if ((fd_acc = accept(fd, (struct sockaddr *)&addr, &len)) < 0) { prmsg("accept() failed at %s line %d\n", __FILE__, __LINE__); return -1; } return fd_acc;}static server_return_t server_read(void){ char buf[256]; struct server_event *e = (struct server_event *)buf; int fd = server_fds.fd_acc; int status = 0; if (read_event(fd, e, 256) < 0) { prmsg("failed to read event packet from socket\n"); return SERVER_RESTART; } switch (e->event) { case DLD_EVENT_TADD: status = server_tadd(e); break; case DLD_EVENT_TDEL: status = server_tdel(e); break; case DLD_EVENT_TKILL: status = server_tkill(e); break; case DLD_EVENT_GETSTAT_TASKENT: taskent_sendstat(fd); sendback_event(fd, DLD_EVENT_DONE); break; case DLD_EVENT_GETSTAT_MEMMGR: status = server_sendstat_memmgr(fd); break; case DLD_EVENT_GETSTAT_SYMBOL: status = server_sendstat_symbol(fd); break; case DLD_EVENT_GETSTAT_SECTION: status = server_sendstat_section(fd); break; case DLD_EVENT_MEMDUMP: status = server_memdump(fd, e); break; #ifndef DSP_EMULATION case DLD_EVENT_DSP_RUN: status = server_dsp_run(fd); break; case DLD_EVENT_DSP_RESET: status = server_dsp_reset(fd); break; case DLD_EVENT_RSTVECT: status = server_setrstvect(fd, e); break; case DLD_EVENT_CPU_IDLE: status = server_cpu_idle(fd); break; case DLD_EVENT_DSPCFG: status = server_dspconfig(fd); break; case DLD_EVENT_DSPUNCFG: status = server_dspunconfig(fd); break; case DLD_EVENT_SUSPEND: status = server_suspend(fd); break; case DLD_EVENT_RESUME: status = server_resume(fd); break; case DLD_EVENT_EXMAP: status = server_exmap(fd, e); break; case DLD_EVENT_MMUINIT: status = server_mmuinit(fd); break; case DLD_EVENT_MAPFLUSH: status = server_mapflush(fd); break; case DLD_EVENT_MBSEND: status = server_mbsend(fd, e); break;#endif /* DSP_EMULATION */ case DLD_EVENT_TERMINATE: prmsg("Terminating...\n"); sendback_event(fd, DLD_EVENT_DONE); return SERVER_DONE; case DLD_EVENT_RESTART: prmsg("Restarting...\n"); sendback_event(fd, DLD_EVENT_DONE); return SERVER_RESTART; default: sendback_event(fd, DLD_EVENT_ERROR); prmsg("unknown event packet (%d) received on socket\n", e->event); return SERVER_RESTART; } if (status < 0) return SERVER_RESTART; return SERVER_OK;}static server_return_t read_all_fds(fd_set testfds){#ifdef USE_FORK int i;#endif if (FD_ISSET(server_fds.fd_sock, &testfds)) { if ((server_fds.fd_acc = server_accept(server_fds.fd_sock)) < 0) return SERVER_RESTART; FD_SET(server_fds.fd_acc, &server_fds.set); } if ((server_fds.fd_acc >= 0) && FD_ISSET(server_fds.fd_acc, &testfds)) { server_return_t ret; ret = server_read(); close(server_fds.fd_acc); FD_CLR(server_fds.fd_acc, &server_fds.set); server_fds.fd_acc = -1; return ret; }#ifdef USE_FORK for (i = 0; i < MAX_CHILDREN; i++) { int fd = server_fds.fd_pipe[i]; if ((fd >= 0) && FD_ISSET(fd, &testfds)) { int ret; ret = read_pipe(fd); close(fd); FD_CLR(fd, &server_fds.set); server_fds.fd_pipe[i] = -1; if (ret < 0) return SERVER_RESTART; } }#endif#ifndef DSP_EMULATION if (FD_ISSET(server_fds.fd_twch, &testfds)) { if (read_twch() < 0) return SERVER_RESTART; FD_SET(server_fds.fd_twch, &server_fds.set); } if (FD_ISSET(server_fds.fd_err, &testfds)) { server_return_t ret; if ((ret = read_errdt(server_fds.fd_err)) != SERVER_OK) return ret; FD_SET(server_fds.fd_err, &server_fds.set); }#endif return SERVER_OK;}server_return_t server(void){ server_return_t ret; struct timeval timeout;#ifdef USE_FORK int i;#endif#ifndef DSP_EMULATION if ((server_fds.fd_twch = open(DEVNAME_TWCH, O_RDONLY)) < 0) { prmsg("%s open failed\n", DEVNAME_TWCH); return SERVER_ERROR; } if ((server_fds.fd_err = open(DEVNAME_ERR, O_RDONLY)) < 0) { prmsg("%s open failed\n", DEVNAME_ERR); return SERVER_ERROR; }#endif if (taskent_mkdev(server_fds.fd_twch) < 0) return SERVER_ERROR; if ((server_fds.fd_sock = server_open(SOCK_NAME)) < 0) return SERVER_ERROR; FD_ZERO(&server_fds.set);#ifndef DSP_EMULATION FD_SET(server_fds.fd_twch, &server_fds.set); FD_SET(server_fds.fd_err, &server_fds.set);#endif FD_SET(server_fds.fd_sock, &server_fds.set); server_fds.fd_acc = -1;#ifdef USE_FORK for (i = 0; i < MAX_CHILDREN; i++) { server_fds.fd_pipe[i] = -1; }#endif /* USE_FORK */ timeout.tv_sec = 10; timeout.tv_usec = 0; for (;;) { fd_set testfds = server_fds.set; int sel_result; sel_result = select(FD_SETSIZE, &testfds, NULL, NULL, &timeout); if (signal_received) { if (signal_action == SERVER_OK) { signal_received = 0; continue; } else break; } if (sel_result < 0) { prmsg("select() failed at %s line %d\n", __FILE__, __LINE__); ret = SERVER_ERROR; break; } else if (sel_result == 0) { /* timeout */#if !(defined DSP_EMULATION) && (defined ENABLE_POLL) int cfd; int status; if (suspend) goto poll_out; if (binary_version < 0x00030003) goto poll_out; /* * we assume this program runs on Linux, * so the timeout value is decreased within * select(), therefore timeout occurs even if * other events wakes select() up frequently. */ if ((cfd = open(DEVNAME_CONTROL, O_RDWR)) < 0) { prmsg("%s open failed at %s line %d\n", DEVNAME_CONTROL, __FILE__, __LINE__); ret = SERVER_RESTART; break; } /* FIXME: fork this polling process */ status = ioctl(cfd, OMAP_DSP_IOCTL_POLL); close(cfd); if (status < 0) { ret = SERVER_RESTART; break; }poll_out:#endif /* !(defined DSP_EMULATION) && (defined ENABLE_POLL) */ timeout.tv_sec = 10; timeout.tv_usec = 0; } else { if ((ret = read_all_fds(testfds)) != SERVER_OK) break; } } taskent_rmdev(server_fds.fd_twch); if (server_fds.fd_acc > 0) close(server_fds.fd_acc); server_close(server_fds.fd_sock, SOCK_NAME);#ifndef DSP_EMULATION close(server_fds.fd_twch); close(server_fds.fd_err);#endif /* signal overrides poll timeout or other error */ if (signal_received) ret = signal_action; return ret;}#undef SIGHUP_RESTARTvoid dspsig_handler(int signum){ prmsg("receiving signal %d\n", signum); signal_received = signum; if (signum == SIGCHLD) { pid_t pid; signal_action = SERVER_OK; do { pid = waitpid(-1, NULL, WNOHANG); } while (pid > 0); return; } if (signum == SIGKILL) exit(0); signal_action = SERVER_DONE;#ifdef SIGHUP_RESTART if (signum == SIGHUP) signal_action = SERVER_RESTART;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -