⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cardmgr.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* 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 + -