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