📄 cardmgr.c
字号:
break; } } else { /* this is a 2.4 kernel; hotplug handles these cards */ s->state |= SOCKET_HOTPLUG; syslog(LOG_INFO, "socket %d: CardBus hotplug device", ns); //beep(BEEP_TIME, BEEP_OK); return NULL; } } /* Try for a FUNCID match */ if (!card && (funcid.func != 0xff)) { for (card = root_func; card; card = card->next) if (card->id.func.funcid == funcid.func) break; } if (card) { syslog(LOG_INFO, "socket %d: %s", ns, card->name); beep(BEEP_TIME, BEEP_OK); if (verbose) log_card_info(vers, &manfid, &funcid, &pci_id); return card; } if (!blank_card || (status.CardState & CS_EVENT_CB_DETECT) || manfid.manf || manfid.card || pci_id.vendor || vers) { syslog(LOG_INFO, "unsupported card in socket %d", ns); if (one_pass) return NULL; beep(BEEP_TIME, BEEP_ERR); log_card_info(vers, &manfid, &funcid, &pci_id); write_stab(); return NULL; } else { card = blank_card; syslog(LOG_INFO, "socket %d: %s", ns, card->name); beep(BEEP_TIME, BEEP_WARN); return card; }}/*====================================================================*/static void load_config(void){ if (chdir(configpath) != 0) { syslog(LOG_ERR, "chdir to %s failed: %m", configpath); exit(EXIT_FAILURE); } if (parse_configfile("config") != 0) exit(EXIT_FAILURE); if (root_device == NULL) syslog(LOG_WARNING, "no device drivers defined"); if ((root_card == NULL) && (root_func == NULL)) syslog(LOG_WARNING, "no cards defined");}/*====================================================================*/static void free_card(card_info_t *card){ if (card && (--card->refs == 0)) { int i; free(card->name); switch(card->ident_type) { case VERS_1_IDENT: for (i = 0; i < card->id.vers.ns; i++) free(card->id.vers.pi[i]); break; case TUPLE_IDENT: free(card->id.tuple.info); break; default: break; } free(card); }}static void free_device(device_info_t *dev){ if (dev && (--dev->refs == 0)) { int i; for (i = 0; i < dev->modules; i++) { free(dev->module[i]); if (dev->opts[i]) free(dev->opts[i]); } if (dev->class) free(dev->class); free(dev); }}static void free_mtd(mtd_ident_t *mtd){ if (mtd && (--mtd->refs == 0)) { free(mtd->name); free(mtd->module); free(mtd); }}static void free_config(void){ while (root_adjust != NULL) { adjust_list_t *adj = root_adjust; root_adjust = root_adjust->next; free(adj); } while (root_device != NULL) { device_info_t *dev = root_device; root_device = root_device->next; free_device(dev); } while (root_card != NULL) { card_info_t *card = root_card; root_card = root_card->next; free_card(card); } while (root_func != NULL) { card_info_t *card = root_func; root_func = root_func->next; free_card(card); } blank_card = NULL; while (root_mtd != NULL) { mtd_ident_t *mtd = root_mtd; root_mtd = root_mtd->next; free_mtd(mtd); } default_mtd = NULL;}/*====================================================================*/static int execute(char *msg, char *cmd){ int ret; FILE *f; char line[256]; syslog(LOG_INFO, "executing: '%s'", cmd); strcat(cmd, " 2>&1"); f = popen(cmd, "r"); while (fgets(line, 255, f)) { line[strlen(line)-1] = '\0'; syslog(LOG_INFO, "+ %s", line); } ret = pclose(f); if (WIFEXITED(ret)) { if (WEXITSTATUS(ret)) syslog(LOG_INFO, "%s exited with status %d", msg, WEXITSTATUS(ret)); return WEXITSTATUS(ret); } else syslog(LOG_INFO, "%s exited on signal %d", msg, WTERMSIG(ret)); return -1;}/*====================================================================*/static int execute_on_dev(char *action, char *class, char *dev){ /* Fixed length strings are ok here */ char msg[128], cmd[128]; sprintf(msg, "%s cmd", action); sprintf(cmd, "./%s %s %s", class, action, dev); return execute(msg, cmd);}static int execute_on_all(char *cmd, char *class, int sn, int fn){ socket_info_t *s = &socket[sn]; bind_info_t *bind; int ret = 0; for (bind = s->bind[fn]; bind != NULL; bind = bind->next) if (bind->name[0] && (bind->name[2] != '#')) ret |= execute_on_dev(cmd, class, bind->name); return ret;}/*====================================================================*/typedef struct module_list_t { char *mod; int usage; struct module_list_t *next;} module_list_t;static module_list_t *module_list = NULL;static int try_insmod(char *mod, char *opts){ char *cmd = malloc(strlen(mod) + strlen(modpath) + (opts ? strlen(opts) : 0) + 30); int ret; strcpy(cmd, "insmod "); if (strchr(mod, '/') != NULL) sprintf(cmd+7, "%s/%s.o", modpath, mod); else sprintf(cmd+7, "%s/pcmcia/%s.o", modpath, mod); if (access(cmd+7, R_OK) != 0) { syslog(LOG_INFO, "module %s not available", cmd+7); free(cmd); return -1; } if (opts) { strcat(cmd, " "); strcat(cmd, opts); } ret = execute("insmod", cmd); free(cmd); return ret;}static int try_modprobe(char *mod, char *opts){ char *cmd = malloc(strlen(mod) + (opts ? strlen(opts) : 0) + 20); char *s = strrchr(mod, '/'); int ret; sprintf(cmd, "modprobe %s", (s) ? s+1 : mod); if (opts) { strcat(cmd, " "); strcat(cmd, opts); } ret = execute("modprobe", cmd); free(cmd); return ret;}static void install_module(char *mod, char *opts){ module_list_t *ml; for (ml = module_list; ml != NULL; ml = ml->next) if (strcmp(mod, ml->mod) == 0) break; if (ml == NULL) { ml = (module_list_t *)malloc(sizeof(struct module_list_t)); ml->mod = mod; ml->usage = 0; ml->next = module_list; module_list = ml; } ml->usage++; if (ml->usage != 1) return; if (access("/proc/bus/pccard/drivers", R_OK) == 0) { FILE *f = fopen("/proc/bus/pccard/drivers", "r"); if (f) { char a[61], s[33]; while (fgets(a, 60, f)) { int is_kernel; sscanf(a, "%s %d", s, &is_kernel); if (strcmp(s, mod) != 0) continue; /* If it isn't a module, we won't try to rmmod */ ml->usage += is_kernel; fclose(f); return; } fclose(f); } } if (do_modprobe) { if (try_modprobe(mod, opts) != 0) try_insmod(mod, opts); } else { if (try_insmod(mod, opts) != 0) try_modprobe(mod, opts); }}static void remove_module(char *mod){ char *s, cmd[128]; module_list_t *ml; for (ml = module_list; ml != NULL; ml = ml->next) if (strcmp(mod, ml->mod) == 0) break; if (ml != NULL) { ml->usage--; if (ml->usage == 0) { /* Strip off leading path names */ s = strrchr(mod, '/'); s = (s) ? s+1 : mod; sprintf(cmd, do_modprobe ? "modprobe -r %s" : "rmmod %s", s); execute(do_modprobe ? "modprobe" : "rmmod", cmd); } }}/*====================================================================*/static mtd_ident_t *lookup_mtd(region_info_t *region){ mtd_ident_t *mtd; int match = 0; for (mtd = root_mtd; mtd; mtd = mtd->next) { switch (mtd->mtd_type) { case JEDEC_MTD: if ((mtd->jedec_mfr == region->JedecMfr) && (mtd->jedec_info == region->JedecInfo)) { match = 1; break; } case DTYPE_MTD: break; default: break; } if (match) break; } if (mtd) return mtd; else return default_mtd;}/*====================================================================*/static void bind_mtd(int sn){ socket_info_t *s = &socket[sn]; region_info_t region; bind_info_t bind; mtd_info_t mtd_info; mtd_ident_t *mtd; int i, attr, ret, nr; nr = 0; for (attr = 0; attr < 2; attr++) { region.Attributes = attr; ret = ioctl(s->fd, DS_GET_FIRST_REGION, ®ion); while (ret == 0) { mtd = lookup_mtd(®ion); if (mtd) { /* Have we seen this MTD before? */ for (i = 0; i < nr; i++) if (s->mtd[i] == mtd) break; if (i == nr) { install_module(mtd->module, mtd->opts); s->mtd[nr] = mtd; mtd->refs++; nr++; } syslog(LOG_INFO, " %s memory region at 0x%x: %s", attr ? "Attribute" : "Common", region.CardOffset, mtd->name); /* Bind MTD to this region */ strcpy(mtd_info.dev_info, s->mtd[i]->module); mtd_info.Attributes = region.Attributes; mtd_info.CardOffset = region.CardOffset; if (ioctl(s->fd, DS_BIND_MTD, &mtd_info) != 0) { syslog(LOG_INFO, "bind MTD '%s' to region at 0x%x failed: %m", (char *)mtd_info.dev_info, region.CardOffset); } } ret = ioctl(s->fd, DS_GET_NEXT_REGION, ®ion); } } s->mtd[nr] = NULL; /* Now bind each unique MTD as a normal client of this socket */ for (i = 0; i < nr; i++) { strcpy(bind.dev_info, s->mtd[i]->module); bind.function = 0; if (ioctl(s->fd, DS_BIND_REQUEST, &bind) != 0) syslog(LOG_INFO, "bind MTD '%s' to socket %d failed: %m", (char *)bind.dev_info, sn); }}/*====================================================================*/static void update_cis(socket_info_t *s){ cisdump_t cis; FILE *f = fopen(s->card->cis_file, "r"); if (f == NULL) syslog(LOG_ERR, "could not open '%s': %m", s->card->cis_file); else { cis.Length = fread(cis.Data, 1, CISTPL_MAX_CIS_SIZE, f); fclose(f); if (ioctl(s->fd, DS_REPLACE_CIS, &cis) != 0) syslog(LOG_ERR, "could not replace CIS: %m"); }}/*====================================================================*/static void do_insert(int sn){ socket_info_t *s = &socket[sn]; card_info_t *card; device_info_t **dev; bind_info_t *bind, **tail; int i, j, ret; /* Already identified? */ if ((s->card != NULL) && (s->card != blank_card)) return; if (verbose) syslog(LOG_INFO, "initializing socket %d", sn); card = lookup_card(sn); if (s->state & SOCKET_HOTPLUG) { write_stab(); return; } /* Make sure we've learned something new before continuing */ if (card == s->card) return; s->card = card; card->refs++; if (card->cis_file) update_cis(s); dev = card->device; /* Set up MTD's */ for (i = 0; i < card->bindings; i++) if (dev[i]->needs_mtd) break; if (i < card->bindings) bind_mtd(sn); /* Install kernel modules */ for (i = 0; i < card->bindings; i++) { dev[i]->refs++; for (j = 0; j < dev[i]->modules; j++) install_module(dev[i]->module[j], dev[i]->opts[j]); } /* Bind drivers by their dev_info identifiers */ for (i = 0; i < card->bindings; i++) { bind = calloc(1, sizeof(bind_info_t)); strcpy((char *)bind->dev_info, (char *)dev[i]->dev_info); if (strcmp(bind->dev_info, "cb_enabler") == 0) bind->function = BIND_FN_ALL; else bind->function = card->dev_fn[i]; if (ioctl(s->fd, DS_BIND_REQUEST, bind) != 0) { if (errno == EBUSY) { syslog(LOG_INFO, "'%s' already bound to socket %d", (char *)bind->dev_info, sn); } else { syslog(LOG_INFO, "bind '%s' to socket %d failed: %m", (char *)bind->dev_info, sn); beep(BEEP_TIME, BEEP_ERR); write_stab(); return; } } for (ret = j = 0; j < 10; j++) { ret = ioctl(s->fd, DS_GET_DEVICE_INFO, bind); if ((ret == 0) || (errno != EAGAIN)) break; usleep(100000); } if (ret != 0) { syslog(LOG_INFO, "get dev info on socket %d failed: %m", sn); if ((errno == EAGAIN) && (strcmp(dev[i]->module[dev[i]->modules-1], (char *)bind->dev_info) != 0)) syslog(LOG_INFO, "wrong module '%s' for device '%s'?", dev[i]->module[dev[i]->modules-1], (char *)bind->dev_info); ioctl(s->fd, DS_UNBIND_REQUEST, bind); beep(BEEP_TIME, BEEP_ERR); write_stab(); return; } tail = &s->bind[i]; while (ret == 0) { bind_info_t *old; if ((strlen(bind->name) > 3) && (bind->name[2] == '#')) xlate_scsi_name(bind); old = *tail = bind; tail = (bind_info_t **)&bind->next; bind = (bind_info_t *)malloc(sizeof(bind_info_t)); memcpy(bind, old, sizeof(bind_info_t)); ret = ioctl(s->fd, DS_GET_NEXT_DEVICE, bind); } *tail = NULL; free(bind); write_stab(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -