162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/fs.h>
362306a36Sopenharmony_ci#include <linux/init.h>
462306a36Sopenharmony_ci#include <linux/proc_fs.h>
562306a36Sopenharmony_ci#include <linux/seq_file.h>
662306a36Sopenharmony_ci#include <linux/blkdev.h>
762306a36Sopenharmony_ci#include "internal.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistatic int devinfo_show(struct seq_file *f, void *v)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	int i = *(loff_t *) v;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	if (i < CHRDEV_MAJOR_MAX) {
1462306a36Sopenharmony_ci		if (i == 0)
1562306a36Sopenharmony_ci			seq_puts(f, "Character devices:\n");
1662306a36Sopenharmony_ci		chrdev_show(f, i);
1762306a36Sopenharmony_ci	}
1862306a36Sopenharmony_ci#ifdef CONFIG_BLOCK
1962306a36Sopenharmony_ci	else {
2062306a36Sopenharmony_ci		i -= CHRDEV_MAJOR_MAX;
2162306a36Sopenharmony_ci		if (i == 0)
2262306a36Sopenharmony_ci			seq_puts(f, "\nBlock devices:\n");
2362306a36Sopenharmony_ci		blkdev_show(f, i);
2462306a36Sopenharmony_ci	}
2562306a36Sopenharmony_ci#endif
2662306a36Sopenharmony_ci	return 0;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic void *devinfo_start(struct seq_file *f, loff_t *pos)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	if (*pos < (BLKDEV_MAJOR_MAX + CHRDEV_MAJOR_MAX))
3262306a36Sopenharmony_ci		return pos;
3362306a36Sopenharmony_ci	return NULL;
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic void *devinfo_next(struct seq_file *f, void *v, loff_t *pos)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	(*pos)++;
3962306a36Sopenharmony_ci	if (*pos >= (BLKDEV_MAJOR_MAX + CHRDEV_MAJOR_MAX))
4062306a36Sopenharmony_ci		return NULL;
4162306a36Sopenharmony_ci	return pos;
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic void devinfo_stop(struct seq_file *f, void *v)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	/* Nothing to do */
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic const struct seq_operations devinfo_ops = {
5062306a36Sopenharmony_ci	.start = devinfo_start,
5162306a36Sopenharmony_ci	.next  = devinfo_next,
5262306a36Sopenharmony_ci	.stop  = devinfo_stop,
5362306a36Sopenharmony_ci	.show  = devinfo_show
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic int __init proc_devices_init(void)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	struct proc_dir_entry *pde;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	pde = proc_create_seq("devices", 0, NULL, &devinfo_ops);
6162306a36Sopenharmony_ci	pde_make_permanent(pde);
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_cifs_initcall(proc_devices_init);
65