ide: /proc/ide/hd*/settings rework
[safe/jmp/linux-2.6] / drivers / ide / ide-proc.c
1 /*
2  *  Copyright (C) 1997-1998     Mark Lord
3  *  Copyright (C) 2003          Red Hat <alan@redhat.com>
4  *
5  *  Some code was moved here from ide.c, see it for original copyrights.
6  */
7
8 /*
9  * This is the /proc/ide/ filesystem implementation.
10  *
11  * Drive/Driver settings can be retrieved by reading the drive's
12  * "settings" files.  e.g.    "cat /proc/ide0/hda/settings"
13  * To write a new value "val" into a specific setting "name", use:
14  *   echo "name:val" >/proc/ide/ide0/hda/settings
15  */
16
17 #include <linux/module.h>
18
19 #include <asm/uaccess.h>
20 #include <linux/errno.h>
21 #include <linux/proc_fs.h>
22 #include <linux/stat.h>
23 #include <linux/mm.h>
24 #include <linux/pci.h>
25 #include <linux/ctype.h>
26 #include <linux/ide.h>
27 #include <linux/seq_file.h>
28
29 #include <asm/io.h>
30
31 static struct proc_dir_entry *proc_ide_root;
32
33 static int proc_ide_read_imodel
34         (char *page, char **start, off_t off, int count, int *eof, void *data)
35 {
36         ide_hwif_t      *hwif = (ide_hwif_t *) data;
37         int             len;
38         const char      *name;
39
40         switch (hwif->chipset) {
41         case ide_generic:       name = "generic";       break;
42         case ide_pci:           name = "pci";           break;
43         case ide_cmd640:        name = "cmd640";        break;
44         case ide_dtc2278:       name = "dtc2278";       break;
45         case ide_ali14xx:       name = "ali14xx";       break;
46         case ide_qd65xx:        name = "qd65xx";        break;
47         case ide_umc8672:       name = "umc8672";       break;
48         case ide_ht6560b:       name = "ht6560b";       break;
49         case ide_rz1000:        name = "rz1000";        break;
50         case ide_trm290:        name = "trm290";        break;
51         case ide_cmd646:        name = "cmd646";        break;
52         case ide_cy82c693:      name = "cy82c693";      break;
53         case ide_4drives:       name = "4drives";       break;
54         case ide_pmac:          name = "mac-io";        break;
55         case ide_au1xxx:        name = "au1xxx";        break;
56         case ide_palm3710:      name = "palm3710";      break;
57         case ide_acorn:         name = "acorn";         break;
58         default:                name = "(unknown)";     break;
59         }
60         len = sprintf(page, "%s\n", name);
61         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
62 }
63
64 static int proc_ide_read_mate
65         (char *page, char **start, off_t off, int count, int *eof, void *data)
66 {
67         ide_hwif_t      *hwif = (ide_hwif_t *) data;
68         int             len;
69
70         if (hwif && hwif->mate)
71                 len = sprintf(page, "%s\n", hwif->mate->name);
72         else
73                 len = sprintf(page, "(none)\n");
74         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
75 }
76
77 static int proc_ide_read_channel
78         (char *page, char **start, off_t off, int count, int *eof, void *data)
79 {
80         ide_hwif_t      *hwif = (ide_hwif_t *) data;
81         int             len;
82
83         page[0] = hwif->channel ? '1' : '0';
84         page[1] = '\n';
85         len = 2;
86         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
87 }
88
89 static int proc_ide_read_identify
90         (char *page, char **start, off_t off, int count, int *eof, void *data)
91 {
92         ide_drive_t     *drive = (ide_drive_t *)data;
93         int             len = 0, i = 0;
94         int             err = 0;
95
96         len = sprintf(page, "\n");
97
98         if (drive) {
99                 __le16 *val = (__le16 *)page;
100
101                 err = taskfile_lib_get_identify(drive, page);
102                 if (!err) {
103                         char *out = ((char *)page) + (SECTOR_WORDS * 4);
104                         page = out;
105                         do {
106                                 out += sprintf(out, "%04x%c",
107                                         le16_to_cpup(val), (++i & 7) ? ' ' : '\n');
108                                 val += 1;
109                         } while (i < (SECTOR_WORDS * 2));
110                         len = out - page;
111                 }
112         }
113         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
114 }
115
116 /**
117  *      ide_find_setting        -       find a specific setting
118  *      @st: setting table pointer
119  *      @name: setting name
120  *
121  *      Scan's the setting table for a matching entry and returns
122  *      this or NULL if no entry is found. The caller must hold the
123  *      setting semaphore
124  */
125
126 static const struct ide_devset *ide_find_setting(const struct ide_devset **st,
127                                                  char *name)
128 {
129         while (*st) {
130                 if (strcmp((*st)->name, name) == 0)
131                         break;
132                 st++;
133         }
134         return *st;
135 }
136
137 /**
138  *      ide_read_setting        -       read an IDE setting
139  *      @drive: drive to read from
140  *      @setting: drive setting
141  *
142  *      Read a drive setting and return the value. The caller
143  *      must hold the ide_setting_mtx when making this call.
144  *
145  *      BUGS: the data return and error are the same return value
146  *      so an error -EINVAL and true return of the same value cannot
147  *      be told apart
148  */
149
150 static int ide_read_setting(ide_drive_t *drive,
151                             const struct ide_devset *setting)
152 {
153         int val = -EINVAL;
154
155         if ((setting->flags & S_READ)) {
156                 unsigned long flags;
157
158                 spin_lock_irqsave(&ide_lock, flags);
159                 val = setting->get(drive);
160                 spin_unlock_irqrestore(&ide_lock, flags);
161         }
162
163         return val;
164 }
165
166 /**
167  *      ide_write_setting       -       read an IDE setting
168  *      @drive: drive to read from
169  *      @setting: drive setting
170  *      @val: value
171  *
172  *      Write a drive setting if it is possible. The caller
173  *      must hold the ide_setting_mtx when making this call.
174  *
175  *      BUGS: the data return and error are the same return value
176  *      so an error -EINVAL and true return of the same value cannot
177  *      be told apart
178  *
179  *      FIXME:  This should be changed to enqueue a special request
180  *      to the driver to change settings, and then wait on a sema for completion.
181  *      The current scheme of polling is kludgy, though safe enough.
182  */
183
184 static int ide_write_setting(ide_drive_t *drive,
185                              const struct ide_devset *setting, int val)
186 {
187         if (!capable(CAP_SYS_ADMIN))
188                 return -EACCES;
189         if (setting->set && (setting->flags & S_NOLOCK))
190                 return setting->set(drive, val);
191         if (!(setting->flags & S_WRITE))
192                 return -EPERM;
193         if (val < setting->min || val > setting->max)
194                 return -EINVAL;
195         if (ide_spin_wait_hwgroup(drive))
196                 return -EBUSY;
197         setting->set(drive, val);
198         spin_unlock_irq(&ide_lock);
199         return 0;
200 }
201
202 static ide_devset_get(xfer_rate, current_speed);
203
204 static int set_xfer_rate (ide_drive_t *drive, int arg)
205 {
206         ide_task_t task;
207         int err;
208
209         if (arg < XFER_PIO_0 || arg > XFER_UDMA_6)
210                 return -EINVAL;
211
212         memset(&task, 0, sizeof(task));
213         task.tf.command = ATA_CMD_SET_FEATURES;
214         task.tf.feature = SETFEATURES_XFER;
215         task.tf.nsect   = (u8)arg;
216         task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
217                         IDE_TFLAG_IN_NSECT;
218
219         err = ide_no_data_taskfile(drive, &task);
220
221         if (!err) {
222                 ide_set_xfer_rate(drive, (u8) arg);
223                 ide_driveid_update(drive);
224         }
225         return err;
226 }
227
228 ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate);
229 ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit);
230 ide_devset_rw_nolock(keepsettings, 0, 1, ksettings);
231 ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq);
232 ide_devset_rw_nolock(using_dma, 0, 1, using_dma);
233
234 ide_devset_w_nolock(pio_mode, 0, 255, pio_mode);
235
236 ide_devset_rw(init_speed, 0, 70, init_speed);
237 ide_devset_rw(nice1, 0, 1, nice1);
238 ide_devset_rw(number, 0, 3, dn);
239
240 static const struct ide_devset *ide_generic_settings[] = {
241         &ide_devset_current_speed,
242         &ide_devset_init_speed,
243         &ide_devset_io_32bit,
244         &ide_devset_keepsettings,
245         &ide_devset_nice1,
246         &ide_devset_number,
247         &ide_devset_pio_mode,
248         &ide_devset_unmaskirq,
249         &ide_devset_using_dma,
250         NULL
251 };
252
253 static void proc_ide_settings_warn(void)
254 {
255         static int warned;
256
257         if (warned)
258                 return;
259
260         printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
261                             "obsolete, and will be removed soon!\n");
262         warned = 1;
263 }
264
265 static int proc_ide_read_settings
266         (char *page, char **start, off_t off, int count, int *eof, void *data)
267 {
268         const struct ide_devset *setting, **g, **d;
269         ide_drive_t     *drive = (ide_drive_t *) data;
270         char            *out = page;
271         int             len, rc, mul_factor, div_factor;
272
273         proc_ide_settings_warn();
274
275         mutex_lock(&ide_setting_mtx);
276         g = ide_generic_settings;
277         d = drive->settings;
278         out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
279         out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
280         while (*g || (d && *d)) {
281                 /* read settings in the alphabetical order */
282                 if (*g && d && *d) {
283                         if (strcmp((*d)->name, (*g)->name) < 0)
284                                 setting = *d++;
285                         else
286                                 setting = *g++;
287                 } else if (d && *d) {
288                         setting = *d++;
289                 } else
290                         setting = *g++;
291                 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
292                 div_factor = setting->divf ? setting->divf(drive) : 1;
293                 out += sprintf(out, "%-24s", setting->name);
294                 rc = ide_read_setting(drive, setting);
295                 if (rc >= 0)
296                         out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
297                 else
298                         out += sprintf(out, "%-16s", "write-only");
299                 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
300                 if (setting->flags & S_READ)
301                         out += sprintf(out, "r");
302                 if (setting->flags & S_WRITE)
303                         out += sprintf(out, "w");
304                 out += sprintf(out, "\n");
305         }
306         len = out - page;
307         mutex_unlock(&ide_setting_mtx);
308         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
309 }
310
311 #define MAX_LEN 30
312
313 static int proc_ide_write_settings(struct file *file, const char __user *buffer,
314                                    unsigned long count, void *data)
315 {
316         ide_drive_t     *drive = (ide_drive_t *) data;
317         char            name[MAX_LEN + 1];
318         int             for_real = 0, mul_factor, div_factor;
319         unsigned long   n;
320
321         const struct ide_devset *setting;
322         char *buf, *s;
323
324         if (!capable(CAP_SYS_ADMIN))
325                 return -EACCES;
326
327         proc_ide_settings_warn();
328
329         if (count >= PAGE_SIZE)
330                 return -EINVAL;
331
332         s = buf = (char *)__get_free_page(GFP_USER);
333         if (!buf)
334                 return -ENOMEM;
335
336         if (copy_from_user(buf, buffer, count)) {
337                 free_page((unsigned long)buf);
338                 return -EFAULT;
339         }
340
341         buf[count] = '\0';
342
343         /*
344          * Skip over leading whitespace
345          */
346         while (count && isspace(*s)) {
347                 --count;
348                 ++s;
349         }
350         /*
351          * Do one full pass to verify all parameters,
352          * then do another to actually write the new settings.
353          */
354         do {
355                 char *p = s;
356                 n = count;
357                 while (n > 0) {
358                         unsigned val;
359                         char *q = p;
360
361                         while (n > 0 && *p != ':') {
362                                 --n;
363                                 p++;
364                         }
365                         if (*p != ':')
366                                 goto parse_error;
367                         if (p - q > MAX_LEN)
368                                 goto parse_error;
369                         memcpy(name, q, p - q);
370                         name[p - q] = 0;
371
372                         if (n > 0) {
373                                 --n;
374                                 p++;
375                         } else
376                                 goto parse_error;
377
378                         val = simple_strtoul(p, &q, 10);
379                         n -= q - p;
380                         p = q;
381                         if (n > 0 && !isspace(*p))
382                                 goto parse_error;
383                         while (n > 0 && isspace(*p)) {
384                                 --n;
385                                 ++p;
386                         }
387
388                         mutex_lock(&ide_setting_mtx);
389                         /* generic settings first, then driver specific ones */
390                         setting = ide_find_setting(ide_generic_settings, name);
391                         if (!setting) {
392                                 if (drive->settings)
393                                         setting = ide_find_setting(drive->settings, name);
394                                 if (!setting) {
395                                         mutex_unlock(&ide_setting_mtx);
396                                         goto parse_error;
397                                 }
398                         }
399                         if (for_real) {
400                                 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
401                                 div_factor = setting->divf ? setting->divf(drive) : 1;
402                                 ide_write_setting(drive, setting, val * div_factor / mul_factor);
403                         }
404                         mutex_unlock(&ide_setting_mtx);
405                 }
406         } while (!for_real++);
407         free_page((unsigned long)buf);
408         return count;
409 parse_error:
410         free_page((unsigned long)buf);
411         printk("proc_ide_write_settings(): parse error\n");
412         return -EINVAL;
413 }
414
415 int proc_ide_read_capacity
416         (char *page, char **start, off_t off, int count, int *eof, void *data)
417 {
418         int len = sprintf(page, "%llu\n", (long long)0x7fffffff);
419         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
420 }
421
422 EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
423
424 int proc_ide_read_geometry
425         (char *page, char **start, off_t off, int count, int *eof, void *data)
426 {
427         ide_drive_t     *drive = (ide_drive_t *) data;
428         char            *out = page;
429         int             len;
430
431         out += sprintf(out, "physical     %d/%d/%d\n",
432                         drive->cyl, drive->head, drive->sect);
433         out += sprintf(out, "logical      %d/%d/%d\n",
434                         drive->bios_cyl, drive->bios_head, drive->bios_sect);
435
436         len = out - page;
437         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
438 }
439
440 EXPORT_SYMBOL(proc_ide_read_geometry);
441
442 static int proc_ide_read_dmodel
443         (char *page, char **start, off_t off, int count, int *eof, void *data)
444 {
445         ide_drive_t     *drive = (ide_drive_t *) data;
446         char            *m = (char *)&drive->id[ATA_ID_PROD];
447         int             len;
448
449         len = sprintf(page, "%.40s\n", m[0] ? m : "(none)");
450         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
451 }
452
453 static int proc_ide_read_driver
454         (char *page, char **start, off_t off, int count, int *eof, void *data)
455 {
456         ide_drive_t     *drive = (ide_drive_t *) data;
457         struct device   *dev = &drive->gendev;
458         ide_driver_t    *ide_drv;
459         int             len;
460
461         if (dev->driver) {
462                 ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
463                 len = sprintf(page, "%s version %s\n",
464                                 dev->driver->name, ide_drv->version);
465         } else
466                 len = sprintf(page, "ide-default version 0.9.newide\n");
467         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
468 }
469
470 static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
471 {
472         struct device *dev = &drive->gendev;
473         int ret = 1;
474         int err;
475
476         device_release_driver(dev);
477         /* FIXME: device can still be in use by previous driver */
478         strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
479         err = device_attach(dev);
480         if (err < 0)
481                 printk(KERN_WARNING "IDE: %s: device_attach error: %d\n",
482                         __func__, err);
483         drive->driver_req[0] = 0;
484         if (dev->driver == NULL) {
485                 err = device_attach(dev);
486                 if (err < 0)
487                         printk(KERN_WARNING
488                                 "IDE: %s: device_attach(2) error: %d\n",
489                                 __func__, err);
490         }
491         if (dev->driver && !strcmp(dev->driver->name, driver))
492                 ret = 0;
493
494         return ret;
495 }
496
497 static int proc_ide_write_driver
498         (struct file *file, const char __user *buffer, unsigned long count, void *data)
499 {
500         ide_drive_t     *drive = (ide_drive_t *) data;
501         char name[32];
502
503         if (!capable(CAP_SYS_ADMIN))
504                 return -EACCES;
505         if (count > 31)
506                 count = 31;
507         if (copy_from_user(name, buffer, count))
508                 return -EFAULT;
509         name[count] = '\0';
510         if (ide_replace_subdriver(drive, name))
511                 return -EINVAL;
512         return count;
513 }
514
515 static int proc_ide_read_media
516         (char *page, char **start, off_t off, int count, int *eof, void *data)
517 {
518         ide_drive_t     *drive = (ide_drive_t *) data;
519         const char      *media;
520         int             len;
521
522         switch (drive->media) {
523         case ide_disk:          media = "disk\n";       break;
524         case ide_cdrom:         media = "cdrom\n";      break;
525         case ide_tape:          media = "tape\n";       break;
526         case ide_floppy:        media = "floppy\n";     break;
527         case ide_optical:       media = "optical\n";    break;
528         default:                media = "UNKNOWN\n";    break;
529         }
530         strcpy(page, media);
531         len = strlen(media);
532         PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
533 }
534
535 static ide_proc_entry_t generic_drive_entries[] = {
536         { "driver",     S_IFREG|S_IRUGO,         proc_ide_read_driver,
537                                                  proc_ide_write_driver },
538         { "identify",   S_IFREG|S_IRUSR,         proc_ide_read_identify, NULL },
539         { "media",      S_IFREG|S_IRUGO,         proc_ide_read_media,    NULL },
540         { "model",      S_IFREG|S_IRUGO,         proc_ide_read_dmodel,   NULL },
541         { "settings",   S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings,
542                                                  proc_ide_write_settings },
543         { NULL, 0, NULL, NULL }
544 };
545
546 static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data)
547 {
548         struct proc_dir_entry *ent;
549
550         if (!dir || !p)
551                 return;
552         while (p->name != NULL) {
553                 ent = create_proc_entry(p->name, p->mode, dir);
554                 if (!ent) return;
555                 ent->data = data;
556                 ent->read_proc = p->read_proc;
557                 ent->write_proc = p->write_proc;
558                 p++;
559         }
560 }
561
562 static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p)
563 {
564         if (!dir || !p)
565                 return;
566         while (p->name != NULL) {
567                 remove_proc_entry(p->name, dir);
568                 p++;
569         }
570 }
571
572 void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
573 {
574         mutex_lock(&ide_setting_mtx);
575         drive->settings = driver->settings;
576         mutex_unlock(&ide_setting_mtx);
577
578         ide_add_proc_entries(drive->proc, driver->proc, drive);
579 }
580
581 EXPORT_SYMBOL(ide_proc_register_driver);
582
583 /**
584  *      ide_proc_unregister_driver      -       remove driver specific data
585  *      @drive: drive
586  *      @driver: driver
587  *
588  *      Clean up the driver specific /proc files and IDE settings
589  *      for a given drive.
590  *
591  *      Takes ide_setting_mtx and ide_lock.
592  *      Caller must hold none of the locks.
593  */
594
595 void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
596 {
597         unsigned long flags;
598
599         ide_remove_proc_entries(drive->proc, driver->proc);
600
601         mutex_lock(&ide_setting_mtx);
602         spin_lock_irqsave(&ide_lock, flags);
603         /*
604          * ide_setting_mtx protects the settings list
605          * ide_lock protects the use of settings
606          *
607          * so we need to hold both, ide_settings_sem because we want to
608          * modify the settings list, and ide_lock because we cannot take
609          * a setting out that is being used.
610          *
611          * OTOH both ide_{read,write}_setting are only ever used under
612          * ide_setting_mtx.
613          */
614         drive->settings = NULL;
615         spin_unlock_irqrestore(&ide_lock, flags);
616         mutex_unlock(&ide_setting_mtx);
617 }
618 EXPORT_SYMBOL(ide_proc_unregister_driver);
619
620 void ide_proc_port_register_devices(ide_hwif_t *hwif)
621 {
622         int     d;
623         struct proc_dir_entry *ent;
624         struct proc_dir_entry *parent = hwif->proc;
625         char name[64];
626
627         for (d = 0; d < MAX_DRIVES; d++) {
628                 ide_drive_t *drive = &hwif->drives[d];
629
630                 if (!drive->present)
631                         continue;
632                 if (drive->proc)
633                         continue;
634
635                 drive->proc = proc_mkdir(drive->name, parent);
636                 if (drive->proc)
637                         ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
638                 sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
639                 ent = proc_symlink(drive->name, proc_ide_root, name);
640                 if (!ent) return;
641         }
642 }
643
644 void ide_proc_unregister_device(ide_drive_t *drive)
645 {
646         if (drive->proc) {
647                 ide_remove_proc_entries(drive->proc, generic_drive_entries);
648                 remove_proc_entry(drive->name, proc_ide_root);
649                 remove_proc_entry(drive->name, drive->hwif->proc);
650                 drive->proc = NULL;
651         }
652 }
653
654 static ide_proc_entry_t hwif_entries[] = {
655         { "channel",    S_IFREG|S_IRUGO,        proc_ide_read_channel,  NULL },
656         { "mate",       S_IFREG|S_IRUGO,        proc_ide_read_mate,     NULL },
657         { "model",      S_IFREG|S_IRUGO,        proc_ide_read_imodel,   NULL },
658         { NULL, 0, NULL, NULL }
659 };
660
661 void ide_proc_register_port(ide_hwif_t *hwif)
662 {
663         if (!hwif->proc) {
664                 hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
665
666                 if (!hwif->proc)
667                         return;
668
669                 ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
670         }
671 }
672
673 void ide_proc_unregister_port(ide_hwif_t *hwif)
674 {
675         if (hwif->proc) {
676                 ide_remove_proc_entries(hwif->proc, hwif_entries);
677                 remove_proc_entry(hwif->name, proc_ide_root);
678                 hwif->proc = NULL;
679         }
680 }
681
682 static int proc_print_driver(struct device_driver *drv, void *data)
683 {
684         ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
685         struct seq_file *s = data;
686
687         seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
688
689         return 0;
690 }
691
692 static int ide_drivers_show(struct seq_file *s, void *p)
693 {
694         int err;
695
696         err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
697         if (err < 0)
698                 printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n",
699                         __func__, err);
700         return 0;
701 }
702
703 static int ide_drivers_open(struct inode *inode, struct file *file)
704 {
705         return single_open(file, &ide_drivers_show, NULL);
706 }
707
708 static const struct file_operations ide_drivers_operations = {
709         .owner          = THIS_MODULE,
710         .open           = ide_drivers_open,
711         .read           = seq_read,
712         .llseek         = seq_lseek,
713         .release        = single_release,
714 };
715
716 void proc_ide_create(void)
717 {
718         proc_ide_root = proc_mkdir("ide", NULL);
719
720         if (!proc_ide_root)
721                 return;
722
723         proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations);
724 }
725
726 void proc_ide_destroy(void)
727 {
728         remove_proc_entry("drivers", proc_ide_root);
729         remove_proc_entry("ide", NULL);
730 }