static int proc_ide_read_settings (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; ide_settings_t *setting = (ide_settings_t *) drive->settings; char *out = page; int len, rc, mul_factor, div_factor; proc_ide_settings_warn(); mutex_lock(&ide_setting_mtx); out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); while (setting) { mul_factor = setting->mul_factor; div_factor = setting->div_factor; out += sprintf(out, "%-24s", setting->name); rc = ide_read_setting(drive, setting); if (rc >= 0) out += sprintf(out, "%-16d", rc * mul_factor / div_factor); else out += sprintf(out, "%-16s", "write-only"); out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); if (setting->rw & SETTING_READ) out += sprintf(out, "r"); if (setting->rw & SETTING_WRITE) out += sprintf(out, "w"); out += sprintf(out, "\n"); setting = setting->next; } len = out - page; mutex_unlock(&ide_setting_mtx); PROC_IDE_READ_RETURN(page, start, off, count, eof, len); }
static int proc_ide_read_settings (char *page, char **start, off_t off, int count, int *eof, void *data) { const struct ide_proc_devset *setting, *g, *d; const struct ide_devset *ds; ide_drive_t *drive = (ide_drive_t *) data; char *out = page; int len, rc, mul_factor, div_factor; proc_ide_settings_warn(); mutex_lock(&ide_setting_mtx); g = ide_generic_settings; d = drive->settings; out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); while (g->name || (d && d->name)) { /* read settings in the alphabetical order */ if (g->name && d && d->name) { if (strcmp(d->name, g->name) < 0) setting = d++; else setting = g++; } else if (d && d->name) { setting = d++; } else setting = g++; mul_factor = setting->mulf ? setting->mulf(drive) : 1; div_factor = setting->divf ? setting->divf(drive) : 1; out += sprintf(out, "%-24s", setting->name); rc = ide_read_setting(drive, setting); if (rc >= 0) out += sprintf(out, "%-16d", rc * mul_factor / div_factor); else out += sprintf(out, "%-16s", "write-only"); out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); ds = setting->setting; if (ds->get) out += sprintf(out, "r"); if (ds->set) out += sprintf(out, "w"); out += sprintf(out, "\n"); } len = out - page; mutex_unlock(&ide_setting_mtx); PROC_IDE_READ_RETURN(page, start, off, count, eof, len); }
static int proc_ide_write_settings(struct file *file, const char __user *buffer, unsigned long count, void *data) { ide_drive_t *drive = (ide_drive_t *) data; char name[MAX_LEN + 1]; int for_real = 0, mul_factor, div_factor; unsigned long n; const struct ide_proc_devset *setting; char *buf, *s; if (!capable(CAP_SYS_ADMIN)) return -EACCES; proc_ide_settings_warn(); if (count >= PAGE_SIZE) return -EINVAL; s = buf = (char *)__get_free_page(GFP_USER); if (!buf) return -ENOMEM; if (copy_from_user(buf, buffer, count)) { free_page((unsigned long)buf); return -EFAULT; } buf[count] = '\0'; /* * Skip over leading whitespace */ while (count && isspace(*s)) { --count; ++s; } /* * Do one full pass to verify all parameters, * then do another to actually write the new settings. */ do { char *p = s; n = count; while (n > 0) { unsigned val; char *q = p; while (n > 0 && *p != ':') { --n; p++; } if (*p != ':') goto parse_error; if (p - q > MAX_LEN) goto parse_error; memcpy(name, q, p - q); name[p - q] = 0; if (n > 0) { --n; p++; } else goto parse_error; val = simple_strtoul(p, &q, 10); n -= q - p; p = q; if (n > 0 && !isspace(*p)) goto parse_error; while (n > 0 && isspace(*p)) { --n; ++p; } mutex_lock(&ide_setting_mtx); /* generic settings first, then driver specific ones */ setting = ide_find_setting(ide_generic_settings, name); if (!setting) { if (drive->settings) setting = ide_find_setting(drive->settings, name); if (!setting) { mutex_unlock(&ide_setting_mtx); goto parse_error; } } if (for_real) { mul_factor = setting->mulf ? setting->mulf(drive) : 1; div_factor = setting->divf ? setting->divf(drive) : 1; ide_write_setting(drive, setting, val * div_factor / mul_factor); } mutex_unlock(&ide_setting_mtx); } } while (!for_real++); free_page((unsigned long)buf); return count; parse_error: free_page((unsigned long)buf); printk("proc_ide_write_settings(): parse error\n"); return -EINVAL; }