ide-proc.c revision 441e92dae0b64b577ea5a88861e86805f69e13cf
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 * Also useful, "cat /proc/ide0/hda/[identify, smart_values,
17 * smart_thresholds, capabilities]" will issue an IDENTIFY /
18 * PACKET_IDENTIFY / SMART_READ_VALUES / SMART_READ_THRESHOLDS /
19 * SENSE CAPABILITIES command to /dev/hda, and then dump out the
20 * returned data as 256 16-bit words.  The "hdparm" utility will
21 * be updated someday soon to use this mechanism.
22 *
23 */
24
25#include <linux/module.h>
26
27#include <asm/uaccess.h>
28#include <linux/errno.h>
29#include <linux/proc_fs.h>
30#include <linux/stat.h>
31#include <linux/mm.h>
32#include <linux/pci.h>
33#include <linux/ctype.h>
34#include <linux/hdreg.h>
35#include <linux/ide.h>
36#include <linux/seq_file.h>
37
38#include <asm/io.h>
39
40static struct proc_dir_entry *proc_ide_root;
41
42static int proc_ide_read_imodel
43	(char *page, char **start, off_t off, int count, int *eof, void *data)
44{
45	ide_hwif_t	*hwif = (ide_hwif_t *) data;
46	int		len;
47	const char	*name;
48
49	switch (hwif->chipset) {
50	case ide_generic:	name = "generic";	break;
51	case ide_pci:		name = "pci";		break;
52	case ide_cmd640:	name = "cmd640";	break;
53	case ide_dtc2278:	name = "dtc2278";	break;
54	case ide_ali14xx:	name = "ali14xx";	break;
55	case ide_qd65xx:	name = "qd65xx";	break;
56	case ide_umc8672:	name = "umc8672";	break;
57	case ide_ht6560b:	name = "ht6560b";	break;
58	case ide_rz1000:	name = "rz1000";	break;
59	case ide_trm290:	name = "trm290";	break;
60	case ide_cmd646:	name = "cmd646";	break;
61	case ide_cy82c693:	name = "cy82c693";	break;
62	case ide_4drives:	name = "4drives";	break;
63	case ide_pmac:		name = "mac-io";	break;
64	case ide_au1xxx:	name = "au1xxx";	break;
65	case ide_palm3710:      name = "palm3710";      break;
66	case ide_etrax100:	name = "etrax100";	break;
67	case ide_acorn:		name = "acorn";		break;
68	default:		name = "(unknown)";	break;
69	}
70	len = sprintf(page, "%s\n", name);
71	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
72}
73
74static int proc_ide_read_mate
75	(char *page, char **start, off_t off, int count, int *eof, void *data)
76{
77	ide_hwif_t	*hwif = (ide_hwif_t *) data;
78	int		len;
79
80	if (hwif && hwif->mate && hwif->mate->present)
81		len = sprintf(page, "%s\n", hwif->mate->name);
82	else
83		len = sprintf(page, "(none)\n");
84	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
85}
86
87static int proc_ide_read_channel
88	(char *page, char **start, off_t off, int count, int *eof, void *data)
89{
90	ide_hwif_t	*hwif = (ide_hwif_t *) data;
91	int		len;
92
93	page[0] = hwif->channel ? '1' : '0';
94	page[1] = '\n';
95	len = 2;
96	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
97}
98
99static int proc_ide_read_identify
100	(char *page, char **start, off_t off, int count, int *eof, void *data)
101{
102	ide_drive_t	*drive = (ide_drive_t *)data;
103	int		len = 0, i = 0;
104	int		err = 0;
105
106	len = sprintf(page, "\n");
107
108	if (drive) {
109		unsigned short *val = (unsigned short *) page;
110
111		err = taskfile_lib_get_identify(drive, page);
112		if (!err) {
113			char *out = ((char *)page) + (SECTOR_WORDS * 4);
114			page = out;
115			do {
116				out += sprintf(out, "%04x%c",
117					le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
118				val += 1;
119			} while (i < (SECTOR_WORDS * 2));
120			len = out - page;
121		}
122	}
123	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
124}
125
126/**
127 *	__ide_add_setting	-	add an ide setting option
128 *	@drive: drive to use
129 *	@name: setting name
130 *	@rw: true if the function is read write
131 *	@data_type: type of data
132 *	@min: range minimum
133 *	@max: range maximum
134 *	@mul_factor: multiplication scale
135 *	@div_factor: divison scale
136 *	@data: private data field
137 *	@set: setting
138 *	@auto_remove: setting auto removal flag
139 *
140 *	Removes the setting named from the device if it is present.
141 *	The function takes the settings_lock to protect against
142 *	parallel changes. This function must not be called from IRQ
143 *	context. Returns 0 on success or -1 on failure.
144 *
145 *	BUGS: This code is seriously over-engineered. There is also
146 *	magic about how the driver specific features are setup. If
147 *	a driver is attached we assume the driver settings are auto
148 *	remove.
149 */
150
151static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
152{
153	ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
154
155	mutex_lock(&ide_setting_mtx);
156	while ((*p) && strcmp((*p)->name, name) < 0)
157		p = &((*p)->next);
158	if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
159		goto abort;
160	if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
161		goto abort;
162	strcpy(setting->name, name);
163	setting->rw = rw;
164	setting->data_type = data_type;
165	setting->min = min;
166	setting->max = max;
167	setting->mul_factor = mul_factor;
168	setting->div_factor = div_factor;
169	setting->data = data;
170	setting->set = set;
171
172	setting->next = *p;
173	if (auto_remove)
174		setting->auto_remove = 1;
175	*p = setting;
176	mutex_unlock(&ide_setting_mtx);
177	return 0;
178abort:
179	mutex_unlock(&ide_setting_mtx);
180	kfree(setting);
181	return -1;
182}
183
184int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
185{
186	return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
187}
188
189EXPORT_SYMBOL(ide_add_setting);
190
191/**
192 *	__ide_remove_setting	-	remove an ide setting option
193 *	@drive: drive to use
194 *	@name: setting name
195 *
196 *	Removes the setting named from the device if it is present.
197 *	The caller must hold the setting semaphore.
198 */
199
200static void __ide_remove_setting(ide_drive_t *drive, char *name)
201{
202	ide_settings_t **p, *setting;
203
204	p = (ide_settings_t **) &drive->settings;
205
206	while ((*p) && strcmp((*p)->name, name))
207		p = &((*p)->next);
208	setting = (*p);
209	if (setting == NULL)
210		return;
211
212	(*p) = setting->next;
213
214	kfree(setting->name);
215	kfree(setting);
216}
217
218/**
219 *	auto_remove_settings	-	remove driver specific settings
220 *	@drive: drive
221 *
222 *	Automatically remove all the driver specific settings for this
223 *	drive. This function may not be called from IRQ context. The
224 *	caller must hold ide_setting_mtx.
225 */
226
227static void auto_remove_settings(ide_drive_t *drive)
228{
229	ide_settings_t *setting;
230repeat:
231	setting = drive->settings;
232	while (setting) {
233		if (setting->auto_remove) {
234			__ide_remove_setting(drive, setting->name);
235			goto repeat;
236		}
237		setting = setting->next;
238	}
239}
240
241/**
242 *	ide_find_setting_by_name	-	find a drive specific setting
243 *	@drive: drive to scan
244 *	@name: setting name
245 *
246 *	Scan's the device setting table for a matching entry and returns
247 *	this or NULL if no entry is found. The caller must hold the
248 *	setting semaphore
249 */
250
251static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
252{
253	ide_settings_t *setting = drive->settings;
254
255	while (setting) {
256		if (strcmp(setting->name, name) == 0)
257			break;
258		setting = setting->next;
259	}
260	return setting;
261}
262
263/**
264 *	ide_read_setting	-	read an IDE setting
265 *	@drive: drive to read from
266 *	@setting: drive setting
267 *
268 *	Read a drive setting and return the value. The caller
269 *	must hold the ide_setting_mtx when making this call.
270 *
271 *	BUGS: the data return and error are the same return value
272 *	so an error -EINVAL and true return of the same value cannot
273 *	be told apart
274 */
275
276static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
277{
278	int		val = -EINVAL;
279	unsigned long	flags;
280
281	if ((setting->rw & SETTING_READ)) {
282		spin_lock_irqsave(&ide_lock, flags);
283		switch (setting->data_type) {
284		case TYPE_BYTE:
285			val = *((u8 *) setting->data);
286			break;
287		case TYPE_SHORT:
288			val = *((u16 *) setting->data);
289			break;
290		case TYPE_INT:
291			val = *((u32 *) setting->data);
292			break;
293		}
294		spin_unlock_irqrestore(&ide_lock, flags);
295	}
296	return val;
297}
298
299/**
300 *	ide_write_setting	-	read an IDE setting
301 *	@drive: drive to read from
302 *	@setting: drive setting
303 *	@val: value
304 *
305 *	Write a drive setting if it is possible. The caller
306 *	must hold the ide_setting_mtx when making this call.
307 *
308 *	BUGS: the data return and error are the same return value
309 *	so an error -EINVAL and true return of the same value cannot
310 *	be told apart
311 *
312 *	FIXME:  This should be changed to enqueue a special request
313 *	to the driver to change settings, and then wait on a sema for completion.
314 *	The current scheme of polling is kludgy, though safe enough.
315 */
316
317static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
318{
319	if (!capable(CAP_SYS_ADMIN))
320		return -EACCES;
321	if (setting->set)
322		return setting->set(drive, val);
323	if (!(setting->rw & SETTING_WRITE))
324		return -EPERM;
325	if (val < setting->min || val > setting->max)
326		return -EINVAL;
327	if (ide_spin_wait_hwgroup(drive))
328		return -EBUSY;
329	switch (setting->data_type) {
330	case TYPE_BYTE:
331		*((u8 *) setting->data) = val;
332		break;
333	case TYPE_SHORT:
334		*((u16 *) setting->data) = val;
335		break;
336	case TYPE_INT:
337		*((u32 *) setting->data) = val;
338		break;
339	}
340	spin_unlock_irq(&ide_lock);
341	return 0;
342}
343
344static int set_xfer_rate (ide_drive_t *drive, int arg)
345{
346	ide_task_t task;
347	int err;
348
349	if (arg < 0 || arg > 70)
350		return -EINVAL;
351
352	memset(&task, 0, sizeof(task));
353	task.tf.command = WIN_SETFEATURES;
354	task.tf.feature = SETFEATURES_XFER;
355	task.tf.nsect   = (u8)arg;
356	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
357			IDE_TFLAG_IN_NSECT;
358
359	err = ide_no_data_taskfile(drive, &task);
360
361	if (!err && arg) {
362		ide_set_xfer_rate(drive, (u8) arg);
363		ide_driveid_update(drive);
364	}
365	return err;
366}
367
368/**
369 *	ide_add_generic_settings	-	generic ide settings
370 *	@drive: drive being configured
371 *
372 *	Add the generic parts of the system settings to the /proc files.
373 *	The caller must not be holding the ide_setting_mtx.
374 */
375
376void ide_add_generic_settings (ide_drive_t *drive)
377{
378/*
379 *			  drive		setting name		read/write access				data type	min	max				mul_factor	div_factor	data pointer			set function
380 */
381	__ide_add_setting(drive,	"io_32bit",		drive->no_io_32bit ? SETTING_READ : SETTING_RW,	TYPE_BYTE,	0,	1 + (SUPPORT_VLB_SYNC << 1),	1,		1,		&drive->io_32bit,		set_io_32bit,	0);
382	__ide_add_setting(drive,	"keepsettings",		SETTING_RW,					TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL,		0);
383	__ide_add_setting(drive,	"nice1",		SETTING_RW,					TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL,		0);
384	__ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode,	0);
385	__ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL,		0);
386	__ide_add_setting(drive,	"using_dma",		SETTING_RW,					TYPE_BYTE,	0,	1,				1,		1,		&drive->using_dma,		set_using_dma,	0);
387	__ide_add_setting(drive,	"init_speed",		SETTING_RW,					TYPE_BYTE,	0,	70,				1,		1,		&drive->init_speed,		NULL,		0);
388	__ide_add_setting(drive,	"current_speed",	SETTING_RW,					TYPE_BYTE,	0,	70,				1,		1,		&drive->current_speed,		set_xfer_rate,	0);
389	__ide_add_setting(drive,	"number",		SETTING_RW,					TYPE_BYTE,	0,	3,				1,		1,		&drive->dn,			NULL,		0);
390}
391
392static void proc_ide_settings_warn(void)
393{
394	static int warned;
395
396	if (warned)
397		return;
398
399	printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
400			    "obsolete, and will be removed soon!\n");
401	warned = 1;
402}
403
404static int proc_ide_read_settings
405	(char *page, char **start, off_t off, int count, int *eof, void *data)
406{
407	ide_drive_t	*drive = (ide_drive_t *) data;
408	ide_settings_t	*setting = (ide_settings_t *) drive->settings;
409	char		*out = page;
410	int		len, rc, mul_factor, div_factor;
411
412	proc_ide_settings_warn();
413
414	mutex_lock(&ide_setting_mtx);
415	out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
416	out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
417	while (setting) {
418		mul_factor = setting->mul_factor;
419		div_factor = setting->div_factor;
420		out += sprintf(out, "%-24s", setting->name);
421		rc = ide_read_setting(drive, setting);
422		if (rc >= 0)
423			out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
424		else
425			out += sprintf(out, "%-16s", "write-only");
426		out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
427		if (setting->rw & SETTING_READ)
428			out += sprintf(out, "r");
429		if (setting->rw & SETTING_WRITE)
430			out += sprintf(out, "w");
431		out += sprintf(out, "\n");
432		setting = setting->next;
433	}
434	len = out - page;
435	mutex_unlock(&ide_setting_mtx);
436	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
437}
438
439#define MAX_LEN	30
440
441static int proc_ide_write_settings(struct file *file, const char __user *buffer,
442				   unsigned long count, void *data)
443{
444	ide_drive_t	*drive = (ide_drive_t *) data;
445	char		name[MAX_LEN + 1];
446	int		for_real = 0;
447	unsigned long	n;
448	ide_settings_t	*setting;
449	char *buf, *s;
450
451	if (!capable(CAP_SYS_ADMIN))
452		return -EACCES;
453
454	proc_ide_settings_warn();
455
456	if (count >= PAGE_SIZE)
457		return -EINVAL;
458
459	s = buf = (char *)__get_free_page(GFP_USER);
460	if (!buf)
461		return -ENOMEM;
462
463	if (copy_from_user(buf, buffer, count)) {
464		free_page((unsigned long)buf);
465		return -EFAULT;
466	}
467
468	buf[count] = '\0';
469
470	/*
471	 * Skip over leading whitespace
472	 */
473	while (count && isspace(*s)) {
474		--count;
475		++s;
476	}
477	/*
478	 * Do one full pass to verify all parameters,
479	 * then do another to actually write the new settings.
480	 */
481	do {
482		char *p = s;
483		n = count;
484		while (n > 0) {
485			unsigned val;
486			char *q = p;
487
488			while (n > 0 && *p != ':') {
489				--n;
490				p++;
491			}
492			if (*p != ':')
493				goto parse_error;
494			if (p - q > MAX_LEN)
495				goto parse_error;
496			memcpy(name, q, p - q);
497			name[p - q] = 0;
498
499			if (n > 0) {
500				--n;
501				p++;
502			} else
503				goto parse_error;
504
505			val = simple_strtoul(p, &q, 10);
506			n -= q - p;
507			p = q;
508			if (n > 0 && !isspace(*p))
509				goto parse_error;
510			while (n > 0 && isspace(*p)) {
511				--n;
512				++p;
513			}
514
515			mutex_lock(&ide_setting_mtx);
516			setting = ide_find_setting_by_name(drive, name);
517			if (!setting) {
518				mutex_unlock(&ide_setting_mtx);
519				goto parse_error;
520			}
521			if (for_real)
522				ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
523			mutex_unlock(&ide_setting_mtx);
524		}
525	} while (!for_real++);
526	free_page((unsigned long)buf);
527	return count;
528parse_error:
529	free_page((unsigned long)buf);
530	printk("proc_ide_write_settings(): parse error\n");
531	return -EINVAL;
532}
533
534int proc_ide_read_capacity
535	(char *page, char **start, off_t off, int count, int *eof, void *data)
536{
537	int len = sprintf(page, "%llu\n", (long long)0x7fffffff);
538	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
539}
540
541EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
542
543int proc_ide_read_geometry
544	(char *page, char **start, off_t off, int count, int *eof, void *data)
545{
546	ide_drive_t	*drive = (ide_drive_t *) data;
547	char		*out = page;
548	int		len;
549
550	out += sprintf(out, "physical     %d/%d/%d\n",
551			drive->cyl, drive->head, drive->sect);
552	out += sprintf(out, "logical      %d/%d/%d\n",
553			drive->bios_cyl, drive->bios_head, drive->bios_sect);
554
555	len = out - page;
556	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
557}
558
559EXPORT_SYMBOL(proc_ide_read_geometry);
560
561static int proc_ide_read_dmodel
562	(char *page, char **start, off_t off, int count, int *eof, void *data)
563{
564	ide_drive_t	*drive = (ide_drive_t *) data;
565	struct hd_driveid *id = drive->id;
566	int		len;
567
568	len = sprintf(page, "%.40s\n",
569		(id && id->model[0]) ? (char *)id->model : "(none)");
570	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
571}
572
573static int proc_ide_read_driver
574	(char *page, char **start, off_t off, int count, int *eof, void *data)
575{
576	ide_drive_t	*drive = (ide_drive_t *) data;
577	struct device	*dev = &drive->gendev;
578	ide_driver_t	*ide_drv;
579	int		len;
580
581	if (dev->driver) {
582		ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
583		len = sprintf(page, "%s version %s\n",
584				dev->driver->name, ide_drv->version);
585	} else
586		len = sprintf(page, "ide-default version 0.9.newide\n");
587	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
588}
589
590static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
591{
592	struct device *dev = &drive->gendev;
593	int ret = 1;
594	int err;
595
596	device_release_driver(dev);
597	/* FIXME: device can still be in use by previous driver */
598	strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
599	err = device_attach(dev);
600	if (err < 0)
601		printk(KERN_WARNING "IDE: %s: device_attach error: %d\n",
602			__FUNCTION__, err);
603	drive->driver_req[0] = 0;
604	if (dev->driver == NULL) {
605		err = device_attach(dev);
606		if (err < 0)
607			printk(KERN_WARNING
608				"IDE: %s: device_attach(2) error: %d\n",
609				__FUNCTION__, err);
610	}
611	if (dev->driver && !strcmp(dev->driver->name, driver))
612		ret = 0;
613
614	return ret;
615}
616
617static int proc_ide_write_driver
618	(struct file *file, const char __user *buffer, unsigned long count, void *data)
619{
620	ide_drive_t	*drive = (ide_drive_t *) data;
621	char name[32];
622
623	if (!capable(CAP_SYS_ADMIN))
624		return -EACCES;
625	if (count > 31)
626		count = 31;
627	if (copy_from_user(name, buffer, count))
628		return -EFAULT;
629	name[count] = '\0';
630	if (ide_replace_subdriver(drive, name))
631		return -EINVAL;
632	return count;
633}
634
635static int proc_ide_read_media
636	(char *page, char **start, off_t off, int count, int *eof, void *data)
637{
638	ide_drive_t	*drive = (ide_drive_t *) data;
639	const char	*media;
640	int		len;
641
642	switch (drive->media) {
643	case ide_disk:		media = "disk\n";	break;
644	case ide_cdrom:		media = "cdrom\n";	break;
645	case ide_tape:		media = "tape\n";	break;
646	case ide_floppy:	media = "floppy\n";	break;
647	case ide_optical:	media = "optical\n";	break;
648	default:		media = "UNKNOWN\n";	break;
649	}
650	strcpy(page, media);
651	len = strlen(media);
652	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
653}
654
655static ide_proc_entry_t generic_drive_entries[] = {
656	{ "driver",	S_IFREG|S_IRUGO,	 proc_ide_read_driver,
657						 proc_ide_write_driver },
658	{ "identify",	S_IFREG|S_IRUSR,	 proc_ide_read_identify, NULL },
659	{ "media",	S_IFREG|S_IRUGO,	 proc_ide_read_media,    NULL },
660	{ "model",	S_IFREG|S_IRUGO,	 proc_ide_read_dmodel,   NULL },
661	{ "settings",	S_IFREG|S_IRUSR|S_IWUSR, proc_ide_read_settings,
662						 proc_ide_write_settings },
663	{ NULL,	0, NULL, NULL }
664};
665
666static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data)
667{
668	struct proc_dir_entry *ent;
669
670	if (!dir || !p)
671		return;
672	while (p->name != NULL) {
673		ent = create_proc_entry(p->name, p->mode, dir);
674		if (!ent) return;
675		ent->data = data;
676		ent->read_proc = p->read_proc;
677		ent->write_proc = p->write_proc;
678		p++;
679	}
680}
681
682static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p)
683{
684	if (!dir || !p)
685		return;
686	while (p->name != NULL) {
687		remove_proc_entry(p->name, dir);
688		p++;
689	}
690}
691
692void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
693{
694	ide_add_proc_entries(drive->proc, driver->proc, drive);
695}
696
697EXPORT_SYMBOL(ide_proc_register_driver);
698
699/**
700 *	ide_proc_unregister_driver	-	remove driver specific data
701 *	@drive: drive
702 *	@driver: driver
703 *
704 *	Clean up the driver specific /proc files and IDE settings
705 *	for a given drive.
706 *
707 *	Takes ide_setting_mtx and ide_lock.
708 *	Caller must hold none of the locks.
709 */
710
711void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
712{
713	unsigned long flags;
714
715	ide_remove_proc_entries(drive->proc, driver->proc);
716
717	mutex_lock(&ide_setting_mtx);
718	spin_lock_irqsave(&ide_lock, flags);
719	/*
720	 * ide_setting_mtx protects the settings list
721	 * ide_lock protects the use of settings
722	 *
723	 * so we need to hold both, ide_settings_sem because we want to
724	 * modify the settings list, and ide_lock because we cannot take
725	 * a setting out that is being used.
726	 *
727	 * OTOH both ide_{read,write}_setting are only ever used under
728	 * ide_setting_mtx.
729	 */
730	auto_remove_settings(drive);
731	spin_unlock_irqrestore(&ide_lock, flags);
732	mutex_unlock(&ide_setting_mtx);
733}
734EXPORT_SYMBOL(ide_proc_unregister_driver);
735
736void ide_proc_port_register_devices(ide_hwif_t *hwif)
737{
738	int	d;
739	struct proc_dir_entry *ent;
740	struct proc_dir_entry *parent = hwif->proc;
741	char name[64];
742
743	for (d = 0; d < MAX_DRIVES; d++) {
744		ide_drive_t *drive = &hwif->drives[d];
745
746		if (!drive->present)
747			continue;
748		if (drive->proc)
749			continue;
750
751		drive->proc = proc_mkdir(drive->name, parent);
752		if (drive->proc)
753			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
754		sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
755		ent = proc_symlink(drive->name, proc_ide_root, name);
756		if (!ent) return;
757	}
758}
759
760void ide_proc_unregister_device(ide_drive_t *drive)
761{
762	if (drive->proc) {
763		ide_remove_proc_entries(drive->proc, generic_drive_entries);
764		remove_proc_entry(drive->name, proc_ide_root);
765		remove_proc_entry(drive->name, drive->hwif->proc);
766		drive->proc = NULL;
767	}
768}
769
770static ide_proc_entry_t hwif_entries[] = {
771	{ "channel",	S_IFREG|S_IRUGO,	proc_ide_read_channel,	NULL },
772	{ "mate",	S_IFREG|S_IRUGO,	proc_ide_read_mate,	NULL },
773	{ "model",	S_IFREG|S_IRUGO,	proc_ide_read_imodel,	NULL },
774	{ NULL,	0, NULL, NULL }
775};
776
777void ide_proc_register_port(ide_hwif_t *hwif)
778{
779	if (!hwif->proc) {
780		hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
781
782		if (!hwif->proc)
783			return;
784
785		ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
786	}
787}
788
789#ifdef CONFIG_BLK_DEV_IDEPCI
790void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
791{
792	create_proc_info_entry(name, 0, proc_ide_root, get_info);
793}
794EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
795#endif
796
797void ide_proc_unregister_port(ide_hwif_t *hwif)
798{
799	if (hwif->proc) {
800		ide_remove_proc_entries(hwif->proc, hwif_entries);
801		remove_proc_entry(hwif->name, proc_ide_root);
802		hwif->proc = NULL;
803	}
804}
805
806static int proc_print_driver(struct device_driver *drv, void *data)
807{
808	ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
809	struct seq_file *s = data;
810
811	seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
812
813	return 0;
814}
815
816static int ide_drivers_show(struct seq_file *s, void *p)
817{
818	int err;
819
820	err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
821	if (err < 0)
822		printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n",
823			__FUNCTION__, err);
824	return 0;
825}
826
827static int ide_drivers_open(struct inode *inode, struct file *file)
828{
829	return single_open(file, &ide_drivers_show, NULL);
830}
831
832static const struct file_operations ide_drivers_operations = {
833	.open		= ide_drivers_open,
834	.read		= seq_read,
835	.llseek		= seq_lseek,
836	.release	= single_release,
837};
838
839void proc_ide_create(void)
840{
841	struct proc_dir_entry *entry;
842
843	proc_ide_root = proc_mkdir("ide", NULL);
844
845	if (!proc_ide_root)
846		return;
847
848	entry = create_proc_entry("drivers", 0, proc_ide_root);
849	if (entry)
850		entry->proc_fops = &ide_drivers_operations;
851}
852
853void proc_ide_destroy(void)
854{
855	remove_proc_entry("drivers", proc_ide_root);
856	remove_proc_entry("ide", NULL);
857}
858