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	down(&ide_setting_sem);
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	up(&ide_setting_sem);
181	return 0;
182abort:
183	up(&ide_setting_sem);
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_sem.
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_sem 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
303static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
304{
305	if (!capable(CAP_SYS_ADMIN))
306		return -EACCES;
307	if (setting->set)
308		return setting->set(drive, val);
309	if (!(setting->rw & SETTING_WRITE))
310		return -EPERM;
311	if (val < setting->min || val > setting->max)
312		return -EINVAL;
313	if (ide_spin_wait_hwgroup(drive))
314		return -EBUSY;
315	switch (setting->data_type) {
316		case TYPE_BYTE:
317			*((u8 *) setting->data) = val;
318			break;
319		case TYPE_SHORT:
320			*((u16 *) setting->data) = val;
321			break;
322		case TYPE_INT:
323			*((u32 *) setting->data) = val;
324			break;
325	}
326	spin_unlock_irq(&ide_lock);
327	return 0;
328}
329
330static int set_xfer_rate (ide_drive_t *drive, int arg)
331{
332	int err;
333
334	if (arg < 0 || arg > 70)
335		return -EINVAL;
336
337	err = ide_wait_cmd(drive,
338			WIN_SETFEATURES, (u8) arg,
339			SETFEATURES_XFER, 0, NULL);
340
341	if (!err && arg) {
342		ide_set_xfer_rate(drive, (u8) arg);
343		ide_driveid_update(drive);
344	}
345	return err;
346}
347
348/**
349 *	ide_add_generic_settings	-	generic ide settings
350 *	@drive: drive being configured
351 *
352 *	Add the generic parts of the system settings to the /proc files.
353 *	The caller must not be holding the ide_setting_sem.
354 */
355
356void ide_add_generic_settings (ide_drive_t *drive)
357{
358/*
359 *			  drive		setting name		read/write access				data type	min	max				mul_factor	div_factor	data pointer			set function
360 */
361	__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);
362	__ide_add_setting(drive,	"keepsettings",		SETTING_RW,					TYPE_BYTE,	0,	1,				1,		1,		&drive->keep_settings,		NULL,		0);
363	__ide_add_setting(drive,	"nice1",		SETTING_RW,					TYPE_BYTE,	0,	1,				1,		1,		&drive->nice1,			NULL,		0);
364	__ide_add_setting(drive,	"pio_mode",		SETTING_WRITE,					TYPE_BYTE,	0,	255,				1,		1,		NULL,				set_pio_mode,	0);
365	__ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL,		0);
366	__ide_add_setting(drive,	"using_dma",		SETTING_RW,					TYPE_BYTE,	0,	1,				1,		1,		&drive->using_dma,		set_using_dma,	0);
367	__ide_add_setting(drive,	"init_speed",		SETTING_RW,					TYPE_BYTE,	0,	70,				1,		1,		&drive->init_speed,		NULL,		0);
368	__ide_add_setting(drive,	"current_speed",	SETTING_RW,					TYPE_BYTE,	0,	70,				1,		1,		&drive->current_speed,		set_xfer_rate,	0);
369	__ide_add_setting(drive,	"number",		SETTING_RW,					TYPE_BYTE,	0,	3,				1,		1,		&drive->dn,			NULL,		0);
370}
371
372static void proc_ide_settings_warn(void)
373{
374	static int warned = 0;
375
376	if (warned)
377		return;
378
379	printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is "
380			    "obsolete, and will be removed soon!\n");
381	warned = 1;
382}
383
384static int proc_ide_read_settings
385	(char *page, char **start, off_t off, int count, int *eof, void *data)
386{
387	ide_drive_t	*drive = (ide_drive_t *) data;
388	ide_settings_t	*setting = (ide_settings_t *) drive->settings;
389	char		*out = page;
390	int		len, rc, mul_factor, div_factor;
391
392	proc_ide_settings_warn();
393
394	down(&ide_setting_sem);
395	out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
396	out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
397	while(setting) {
398		mul_factor = setting->mul_factor;
399		div_factor = setting->div_factor;
400		out += sprintf(out, "%-24s", setting->name);
401		if ((rc = ide_read_setting(drive, setting)) >= 0)
402			out += sprintf(out, "%-16d", rc * mul_factor / div_factor);
403		else
404			out += sprintf(out, "%-16s", "write-only");
405		out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
406		if (setting->rw & SETTING_READ)
407			out += sprintf(out, "r");
408		if (setting->rw & SETTING_WRITE)
409			out += sprintf(out, "w");
410		out += sprintf(out, "\n");
411		setting = setting->next;
412	}
413	len = out - page;
414	up(&ide_setting_sem);
415	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
416}
417
418#define MAX_LEN	30
419
420static int proc_ide_write_settings(struct file *file, const char __user *buffer,
421				   unsigned long count, void *data)
422{
423	ide_drive_t	*drive = (ide_drive_t *) data;
424	char		name[MAX_LEN + 1];
425	int		for_real = 0;
426	unsigned long	n;
427	ide_settings_t	*setting;
428	char *buf, *s;
429
430	if (!capable(CAP_SYS_ADMIN))
431		return -EACCES;
432
433	proc_ide_settings_warn();
434
435	if (count >= PAGE_SIZE)
436		return -EINVAL;
437
438	s = buf = (char *)__get_free_page(GFP_USER);
439	if (!buf)
440		return -ENOMEM;
441
442	if (copy_from_user(buf, buffer, count)) {
443		free_page((unsigned long)buf);
444		return -EFAULT;
445	}
446
447	buf[count] = '\0';
448
449	/*
450	 * Skip over leading whitespace
451	 */
452	while (count && isspace(*s)) {
453		--count;
454		++s;
455	}
456	/*
457	 * Do one full pass to verify all parameters,
458	 * then do another to actually write the new settings.
459	 */
460	do {
461		char *p = s;
462		n = count;
463		while (n > 0) {
464			unsigned val;
465			char *q = p;
466
467			while (n > 0 && *p != ':') {
468				--n;
469				p++;
470			}
471			if (*p != ':')
472				goto parse_error;
473			if (p - q > MAX_LEN)
474				goto parse_error;
475			memcpy(name, q, p - q);
476			name[p - q] = 0;
477
478			if (n > 0) {
479				--n;
480				p++;
481			} else
482				goto parse_error;
483
484			val = simple_strtoul(p, &q, 10);
485			n -= q - p;
486			p = q;
487			if (n > 0 && !isspace(*p))
488				goto parse_error;
489			while (n > 0 && isspace(*p)) {
490				--n;
491				++p;
492			}
493
494			down(&ide_setting_sem);
495			setting = ide_find_setting_by_name(drive, name);
496			if (!setting)
497			{
498				up(&ide_setting_sem);
499				goto parse_error;
500			}
501			if (for_real)
502				ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
503			up(&ide_setting_sem);
504		}
505	} while (!for_real++);
506	free_page((unsigned long)buf);
507	return count;
508parse_error:
509	free_page((unsigned long)buf);
510	printk("proc_ide_write_settings(): parse error\n");
511	return -EINVAL;
512}
513
514int proc_ide_read_capacity
515	(char *page, char **start, off_t off, int count, int *eof, void *data)
516{
517	int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
518	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
519}
520
521EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
522
523int proc_ide_read_geometry
524	(char *page, char **start, off_t off, int count, int *eof, void *data)
525{
526	ide_drive_t	*drive = (ide_drive_t *) data;
527	char		*out = page;
528	int		len;
529
530	out += sprintf(out,"physical     %d/%d/%d\n",
531			drive->cyl, drive->head, drive->sect);
532	out += sprintf(out,"logical      %d/%d/%d\n",
533			drive->bios_cyl, drive->bios_head, drive->bios_sect);
534
535	len = out - page;
536	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
537}
538
539EXPORT_SYMBOL(proc_ide_read_geometry);
540
541static int proc_ide_read_dmodel
542	(char *page, char **start, off_t off, int count, int *eof, void *data)
543{
544	ide_drive_t	*drive = (ide_drive_t *) data;
545	struct hd_driveid *id = drive->id;
546	int		len;
547
548	len = sprintf(page, "%.40s\n",
549		(id && id->model[0]) ? (char *)id->model : "(none)");
550	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
551}
552
553static int proc_ide_read_driver
554	(char *page, char **start, off_t off, int count, int *eof, void *data)
555{
556	ide_drive_t	*drive = (ide_drive_t *) data;
557	struct device	*dev = &drive->gendev;
558	ide_driver_t	*ide_drv;
559	int		len;
560
561	if (dev->driver) {
562		ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
563		len = sprintf(page, "%s version %s\n",
564				dev->driver->name, ide_drv->version);
565	} else
566		len = sprintf(page, "ide-default version 0.9.newide\n");
567	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
568}
569
570static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
571{
572	struct device *dev = &drive->gendev;
573	int ret = 1;
574	int err;
575
576	device_release_driver(dev);
577	strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
578	err = device_attach(dev);
579	if (err < 0)
580		printk(KERN_WARNING "IDE: %s: device_attach error: %d\n",
581			__FUNCTION__, err);
582	drive->driver_req[0] = 0;
583	if (dev->driver == NULL) {
584		err = device_attach(dev);
585		if (err < 0)
586			printk(KERN_WARNING
587				"IDE: %s: device_attach(2) error: %d\n",
588				__FUNCTION__, err);
589	}
590	if (dev->driver && !strcmp(dev->driver->name, driver))
591		ret = 0;
592
593	return ret;
594}
595
596static int proc_ide_write_driver
597	(struct file *file, const char __user *buffer, unsigned long count, void *data)
598{
599	ide_drive_t	*drive = (ide_drive_t *) data;
600	char name[32];
601
602	if (!capable(CAP_SYS_ADMIN))
603		return -EACCES;
604	if (count > 31)
605		count = 31;
606	if (copy_from_user(name, buffer, count))
607		return -EFAULT;
608	name[count] = '\0';
609	if (ide_replace_subdriver(drive, name))
610		return -EINVAL;
611	return count;
612}
613
614static int proc_ide_read_media
615	(char *page, char **start, off_t off, int count, int *eof, void *data)
616{
617	ide_drive_t	*drive = (ide_drive_t *) data;
618	const char	*media;
619	int		len;
620
621	switch (drive->media) {
622		case ide_disk:	media = "disk\n";
623				break;
624		case ide_cdrom:	media = "cdrom\n";
625				break;
626		case ide_tape:	media = "tape\n";
627				break;
628		case ide_floppy:media = "floppy\n";
629				break;
630		case ide_optical:media = "optical\n";
631				break;
632		default:	media = "UNKNOWN\n";
633				break;
634	}
635	strcpy(page,media);
636	len = strlen(media);
637	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
638}
639
640static ide_proc_entry_t generic_drive_entries[] = {
641	{ "driver",	S_IFREG|S_IRUGO,	proc_ide_read_driver,	proc_ide_write_driver },
642	{ "identify",	S_IFREG|S_IRUSR,	proc_ide_read_identify,	NULL },
643	{ "media",	S_IFREG|S_IRUGO,	proc_ide_read_media,	NULL },
644	{ "model",	S_IFREG|S_IRUGO,	proc_ide_read_dmodel,	NULL },
645	{ "settings",	S_IFREG|S_IRUSR|S_IWUSR,proc_ide_read_settings,	proc_ide_write_settings },
646	{ NULL,	0, NULL, NULL }
647};
648
649static void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data)
650{
651	struct proc_dir_entry *ent;
652
653	if (!dir || !p)
654		return;
655	while (p->name != NULL) {
656		ent = create_proc_entry(p->name, p->mode, dir);
657		if (!ent) return;
658		ent->data = data;
659		ent->read_proc = p->read_proc;
660		ent->write_proc = p->write_proc;
661		p++;
662	}
663}
664
665static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p)
666{
667	if (!dir || !p)
668		return;
669	while (p->name != NULL) {
670		remove_proc_entry(p->name, dir);
671		p++;
672	}
673}
674
675void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
676{
677	ide_add_proc_entries(drive->proc, driver->proc, drive);
678}
679
680EXPORT_SYMBOL(ide_proc_register_driver);
681
682/**
683 *	ide_proc_unregister_driver	-	remove driver specific data
684 *	@drive: drive
685 *	@driver: driver
686 *
687 *	Clean up the driver specific /proc files and IDE settings
688 *	for a given drive.
689 *
690 *	Takes ide_setting_sem and ide_lock.
691 *	Caller must hold none of the locks.
692 */
693
694void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
695{
696	unsigned long flags;
697
698	ide_remove_proc_entries(drive->proc, driver->proc);
699
700	down(&ide_setting_sem);
701	spin_lock_irqsave(&ide_lock, flags);
702	/*
703	 * ide_setting_sem protects the settings list
704	 * ide_lock protects the use of settings
705	 *
706	 * so we need to hold both, ide_settings_sem because we want to
707	 * modify the settings list, and ide_lock because we cannot take
708	 * a setting out that is being used.
709	 *
710	 * OTOH both ide_{read,write}_setting are only ever used under
711	 * ide_setting_sem.
712	 */
713	auto_remove_settings(drive);
714	spin_unlock_irqrestore(&ide_lock, flags);
715	up(&ide_setting_sem);
716}
717
718EXPORT_SYMBOL(ide_proc_unregister_driver);
719
720static void create_proc_ide_drives(ide_hwif_t *hwif)
721{
722	int	d;
723	struct proc_dir_entry *ent;
724	struct proc_dir_entry *parent = hwif->proc;
725	char name[64];
726
727	for (d = 0; d < MAX_DRIVES; d++) {
728		ide_drive_t *drive = &hwif->drives[d];
729
730		if (!drive->present)
731			continue;
732		if (drive->proc)
733			continue;
734
735		drive->proc = proc_mkdir(drive->name, parent);
736		if (drive->proc)
737			ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
738		sprintf(name,"ide%d/%s", (drive->name[2]-'a')/2, drive->name);
739		ent = proc_symlink(drive->name, proc_ide_root, name);
740		if (!ent) return;
741	}
742}
743
744static void destroy_proc_ide_device(ide_hwif_t *hwif, ide_drive_t *drive)
745{
746	if (drive->proc) {
747		ide_remove_proc_entries(drive->proc, generic_drive_entries);
748		remove_proc_entry(drive->name, proc_ide_root);
749		remove_proc_entry(drive->name, hwif->proc);
750		drive->proc = NULL;
751	}
752}
753
754static void destroy_proc_ide_drives(ide_hwif_t *hwif)
755{
756	int	d;
757
758	for (d = 0; d < MAX_DRIVES; d++) {
759		ide_drive_t *drive = &hwif->drives[d];
760		if (drive->proc)
761			destroy_proc_ide_device(hwif, drive);
762	}
763}
764
765static ide_proc_entry_t hwif_entries[] = {
766	{ "channel",	S_IFREG|S_IRUGO,	proc_ide_read_channel,	NULL },
767	{ "mate",	S_IFREG|S_IRUGO,	proc_ide_read_mate,	NULL },
768	{ "model",	S_IFREG|S_IRUGO,	proc_ide_read_imodel,	NULL },
769	{ NULL,	0, NULL, NULL }
770};
771
772void ide_proc_register_port(ide_hwif_t *hwif)
773{
774	if (!hwif->present)
775		return;
776
777	if (!hwif->proc) {
778		hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
779
780		if (!hwif->proc)
781			return;
782
783		ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
784	}
785
786	create_proc_ide_drives(hwif);
787}
788
789EXPORT_SYMBOL_GPL(ide_proc_register_port);
790
791#ifdef CONFIG_BLK_DEV_IDEPCI
792void ide_pci_create_host_proc(const char *name, get_info_t *get_info)
793{
794	create_proc_info_entry(name, 0, proc_ide_root, get_info);
795}
796
797EXPORT_SYMBOL_GPL(ide_pci_create_host_proc);
798#endif
799
800void ide_proc_unregister_port(ide_hwif_t *hwif)
801{
802	if (hwif->proc) {
803		destroy_proc_ide_drives(hwif);
804		ide_remove_proc_entries(hwif->proc, hwif_entries);
805		remove_proc_entry(hwif->name, proc_ide_root);
806		hwif->proc = NULL;
807	}
808}
809
810static int proc_print_driver(struct device_driver *drv, void *data)
811{
812	ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
813	struct seq_file *s = data;
814
815	seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
816
817	return 0;
818}
819
820static int ide_drivers_show(struct seq_file *s, void *p)
821{
822	int err;
823
824	err = bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
825	if (err < 0)
826		printk(KERN_WARNING "IDE: %s: bus_for_each_drv error: %d\n",
827			__FUNCTION__, err);
828	return 0;
829}
830
831static int ide_drivers_open(struct inode *inode, struct file *file)
832{
833	return single_open(file, &ide_drivers_show, NULL);
834}
835
836static const struct file_operations ide_drivers_operations = {
837	.open		= ide_drivers_open,
838	.read		= seq_read,
839	.llseek		= seq_lseek,
840	.release	= single_release,
841};
842
843void proc_ide_create(void)
844{
845	struct proc_dir_entry *entry;
846
847	proc_ide_root = proc_mkdir("ide", NULL);
848
849	if (!proc_ide_root)
850		return;
851
852	entry = create_proc_entry("drivers", 0, proc_ide_root);
853	if (entry)
854		entry->proc_fops = &ide_drivers_operations;
855}
856
857void proc_ide_destroy(void)
858{
859	remove_proc_entry("drivers", proc_ide_root);
860	remove_proc_entry("ide", NULL);
861}
862