📄 cardmgr.c
字号:
/* Run "start" commands */ for (i = ret = 0; i < card->bindings; i++) if (dev[i]->class) ret |= execute_on_all("start", dev[i]->class, sn, i); beep(BEEP_TIME, (ret) ? BEEP_ERR : BEEP_OK); }/*====================================================================*/static int do_check(int sn){ socket_info_t *s = &socket[sn]; card_info_t *card; device_info_t **dev; int i, ret; card = s->card; if (card == NULL) return 0; /* Run "check" commands */ dev = card->device; for (i = 0; i < card->bindings; i++) { if (dev[i]->class) { ret = execute_on_all("check", dev[i]->class, sn, i); if (ret != 0) return CS_IN_USE; } } return 0;}/*====================================================================*/static void do_remove(int sn){ socket_info_t *s = &socket[sn]; card_info_t *card; device_info_t **dev; bind_info_t *bind; int i, j; if (verbose) syslog(LOG_INFO, "shutting down socket %d", sn); card = s->card; if (card == NULL) goto done; /* Run "stop" commands */ dev = card->device; for (i = 0; i < card->bindings; i++) { if (dev[i]->class) { execute_on_all("stop", dev[i]->class, sn, i); } } /* unbind driver instances */ for (i = 0; i < card->bindings; i++) { if (s->bind[i]) { if (ioctl(s->fd, DS_UNBIND_REQUEST, s->bind[i]) != 0) syslog(LOG_INFO, "unbind '%s' from socket %d failed: %m", (char *)s->bind[i]->dev_info, sn); while (s->bind[i]) { bind = s->bind[i]; s->bind[i] = bind->next; free(bind); } } } for (i = 0; (s->mtd[i] != NULL); i++) { bind_info_t b; strcpy(b.dev_info, s->mtd[i]->module); b.function = 0; if (ioctl(s->fd, DS_UNBIND_REQUEST, &b) != 0) syslog(LOG_INFO, "unbind MTD '%s' from socket %d failed: %m", s->mtd[i]->module, sn); } /* remove kernel modules in inverse order */ for (i = 0; i < card->bindings; i++) { for (j = dev[i]->modules-1; j >= 0; j--) remove_module(dev[i]->module[j]); free_device(dev[i]); } /* Remove any MTD's bound to this socket */ for (i = 0; (s->mtd[i] != NULL); i++) { remove_module(s->mtd[i]->module); free_mtd(s->mtd[i]); s->mtd[i] = NULL; }done: beep(BEEP_TIME, BEEP_OK); free_card(card); s->card = NULL; write_stab();}/*====================================================================*/static void do_suspend(int sn){ socket_info_t *s = &socket[sn]; card_info_t *card; device_info_t **dev; int i, ret; card = s->card; if (card == NULL) return; dev = card->device; for (i = 0; i < card->bindings; i++) { if (dev[i]->class) { ret = execute_on_all("suspend", dev[i]->class, sn, i); if (ret != 0) beep(BEEP_TIME, BEEP_ERR); } }}/*====================================================================*/static void do_resume(int sn){ socket_info_t *s = &socket[sn]; card_info_t *card; device_info_t **dev; int i, ret; card = s->card; if (card == NULL) return; dev = card->device; for (i = 0; i < card->bindings; i++) { if (dev[i]->class) { ret = execute_on_all("resume", dev[i]->class, sn, i); if (ret != 0) beep(BEEP_TIME, BEEP_ERR); } }}/*====================================================================*/static void wait_for_pending(void){ cs_status_t status; int i; status.Function = 0; for (;;) { usleep(100000); for (i = 0; i < sockets; i++) if ((ioctl(socket[i].fd, DS_GET_STATUS, &status) == 0) && (status.CardState & CS_EVENT_CARD_INSERTION)) break; if (i == sockets) break; }}/*====================================================================*/static void free_resources(void){ adjust_list_t *al; int fd = socket[0].fd; for (al = root_adjust; al; al = al->next) { if (al->adj.Action == ADD_MANAGED_RESOURCE) { al->adj.Action = REMOVE_MANAGED_RESOURCE; ioctl(fd, DS_ADJUST_RESOURCE_INFO, &al->adj); } else if ((al->adj.Action == REMOVE_MANAGED_RESOURCE) && (al->adj.Resource == RES_IRQ)) { al->adj.Action = ADD_MANAGED_RESOURCE; ioctl(fd, DS_ADJUST_RESOURCE_INFO, &al->adj); } } }/*====================================================================*/static void adjust_resources(void){ adjust_list_t *al; int ret; char tmp[64]; int fd = socket[0].fd; for (al = root_adjust; al; al = al->next) { ret = ioctl(fd, DS_ADJUST_RESOURCE_INFO, &al->adj); if (ret != 0) { switch (al->adj.Resource) { case RES_MEMORY_RANGE: sprintf(tmp, "memory %#lx-%#lx", al->adj.resource.memory.Base, al->adj.resource.memory.Base + al->adj.resource.memory.Size - 1); break; case RES_IO_RANGE: sprintf(tmp, "IO ports %#x-%#x", al->adj.resource.io.BasePort, al->adj.resource.io.BasePort + al->adj.resource.io.NumPorts - 1); break; case RES_IRQ: sprintf(tmp, "irq %u", al->adj.resource.irq.IRQ); break; } syslog(LOG_INFO, "could not adjust resource: %s: %m", tmp); } }} /*====================================================================*/static void fork_now(void){ int ret; if ((ret = fork()) > 0) _exit(0); if (ret == -1) syslog(LOG_ERR, "forking: %m"); if (setsid() < 0) syslog(LOG_ERR, "detaching from tty: %m");} static void done(void){ syslog(LOG_INFO, "exiting"); unlink(pidfile); unlink(stabfile);}/*====================================================================*//* most recent signal */static int caught_signal = 0;static void catch_signal(int sig){ caught_signal = sig; if (signal(sig, catch_signal) == SIG_ERR) syslog(LOG_INFO, "signal(%d): %m", sig);}static void handle_signal(void){ int i; switch (caught_signal) { case SIGTERM: case SIGINT: for (i = 0; i < sockets; i++) if ((socket[i].state & SOCKET_PRESENT) && (do_check(i) == 0)) do_remove(i); free_resources(); exit(0); break; case SIGHUP: free_resources(); free_config(); syslog(LOG_INFO, "re-loading config file"); load_config(); adjust_resources(); break;#ifdef SIGPWR case SIGPWR: break;#endif }}/*====================================================================*/static int init_sockets(void){ int fd, i; major = lookup_dev("pcmcia"); if (major < 0) { if (major == -ENODEV) syslog(LOG_ERR, "no pcmcia driver in /proc/devices"); else syslog(LOG_ERR, "could not open /proc/devices: %m"); exit(EXIT_FAILURE); } for (fd = -1, i = 0; i < MAX_SOCKS; i++) { fd = open_sock(i, S_IFCHR|S_IREAD|S_IWRITE); if (fd < 0) break; socket[i].fd = fd; socket[i].state = 0; } if ((fd < 0) && (errno != ENODEV) && (errno != ENOENT)) syslog(LOG_ERR, "open_sock(socket %d) failed: %m", i); sockets = i; if (sockets == 0) { if (errno == ENODEV) syslog(LOG_ERR, "no sockets found!"); else if (errno == EBUSY) syslog(LOG_ERR, "another cardmgr is already running?"); return -1; } else syslog(LOG_INFO, "watching %d sockets", sockets); adjust_resources(); return 0;}/*====================================================================*/int main(int argc, char *argv[]){ int optch, errflg; int i, max_fd, ret, event, pass; int delay_fork = 0; struct timeval tv; fd_set fds; if (access("/var/lib/pcmcia", R_OK) == 0) { stabfile = "/var/lib/pcmcia/stab"; } else { stabfile = "/var/run/stab"; } do_modprobe = (access("/sbin/modprobe", X_OK) == 0); errflg = 0; while ((optch = getopt(argc, argv, "Vqdvofc:m:p:s:")) != -1) { switch (optch) { case 'V': fprintf(stderr, "cardmgr version " CS_PKG_RELEASE "\n"); return 0; break; case 'q': be_quiet = 1; break; case 'v': verbose = 1; break; case 'o': one_pass = 1; break; case 'f': delay_fork = 1; break; case 'c': configpath = strdup(optarg); break; case 'd': /* deprecated: do nothing */ break; case 'm': modpath = strdup(optarg); break; case 'p': pidfile = strdup(optarg); break; case 's': stabfile = strdup(optarg); break; default: errflg = 1; break; } } if (errflg || (optind < argc)) { fprintf(stderr, "usage: %s [-V] [-q] [-v] [-o] [-f] " "[-c configpath] [-m modpath]\n " "[-p pidfile] [-s stabfile]\n", argv[0]); exit(EXIT_FAILURE); } openlog("cardmgr", LOG_PID|LOG_PERROR, LOG_DAEMON); putenv("PATH=/bin:/sbin:/usr/bin:/usr/sbin"); if (verbose) putenv("VERBOSE=1"); if (one_pass) putenv("ONEPASS=1"); if (modpath == NULL) { if (access("/lib/modules/preferred", X_OK) == 0) modpath = "/lib/modules/preferred"; else { struct utsname utsname; if (uname(&utsname) != 0) { syslog(LOG_ERR, "uname(): %m"); exit(EXIT_FAILURE); } modpath = (char *)malloc(strlen(utsname.release)+14); sprintf(modpath, "/lib/modules/%s", utsname.release); } } if (access(modpath, X_OK) != 0) syslog(LOG_INFO, "cannot access %s: %m", modpath); /* We default to using modprobe if it is available */ do_modprobe |= (access("/sbin/modprobe", X_OK) == 0); load_config(); if (init_sockets() != 0) exit(EXIT_FAILURE); closelog(); close(0); close(1); close(2); if (!delay_fork && !one_pass) fork_now(); openlog("cardmgr", LOG_PID|LOG_CONS, LOG_DAEMON); syslog(LOG_INFO, "starting, version is " CS_PKG_RELEASE); /* If we've gotten this far, then clean up pid and stab at exit */ atexit(&done); write_pid(); write_stab(); if (signal(SIGHUP, catch_signal) == SIG_ERR) syslog(LOG_ERR, "signal(SIGHUP): %m"); if (signal(SIGTERM, catch_signal) == SIG_ERR) syslog(LOG_ERR, "signal(SIGTERM): %m"); if (signal(SIGINT, catch_signal) == SIG_ERR) syslog(LOG_ERR, "signal(SIGINT): %m");#ifdef SIGPWR if (signal(SIGPWR, catch_signal) == SIG_ERR) syslog(LOG_ERR, "signal(SIGPWR): %m");#endif for (i = max_fd = 0; i < sockets; i++) max_fd = (socket[i].fd > max_fd) ? socket[i].fd : max_fd; /* First select() call: poll, don't wait */ tv.tv_sec = tv.tv_usec = 0; /* Wait for sockets in setup-pending state to settle */ if (one_pass || delay_fork) wait_for_pending(); for (pass = 0; ; pass++) { FD_ZERO(&fds); for (i = 0; i < sockets; i++) FD_SET(socket[i].fd, &fds); while ((ret = select(max_fd+1, &fds, NULL, NULL, ((pass == 0) ? &tv : NULL))) < 0) { if (errno == EINTR) { handle_signal(); } else { syslog(LOG_ERR, "select(): %m"); exit(EXIT_FAILURE); } } for (i = 0; i < sockets; i++) { if (!FD_ISSET(socket[i].fd, &fds)) continue; ret = read(socket[i].fd, &event, 4); if ((ret == -1) && (errno != EAGAIN)) syslog(LOG_INFO, "read(%d): %m\n", i); if (ret != 4) continue; switch (event) { case CS_EVENT_CARD_REMOVAL: socket[i].state = 0; do_remove(i); break; case CS_EVENT_EJECTION_REQUEST: ret = do_check(i); if (ret == 0) { socket[i].state = 0; do_remove(i); } write(socket[i].fd, &ret, 4); break; case CS_EVENT_CARD_INSERTION: case CS_EVENT_INSERTION_REQUEST: socket[i].state |= SOCKET_PRESENT; case CS_EVENT_CARD_RESET: socket[i].state |= SOCKET_READY; do_insert(i); break; case CS_EVENT_RESET_PHYSICAL: socket[i].state &= ~SOCKET_READY; break; case CS_EVENT_PM_SUSPEND: do_suspend(i); break; case CS_EVENT_PM_RESUME: do_resume(i); break; } } if (one_pass) exit(EXIT_SUCCESS); if (delay_fork) { fork_now(); write_pid(); delay_fork = 0; } } /* repeat */ return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -