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