Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/* drivers/nubus/proc.c: Proc FS interface for NuBus.
  3
  4   By David Huggins-Daines <dhd@debian.org>
  5
  6   Much code and many ideas from drivers/pci/proc.c:
  7   Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  8
  9   This is initially based on the Zorro and PCI interfaces.  However,
 10   it works somewhat differently.  The intent is to provide a
 11   structure in /proc analogous to the structure of the NuBus ROM
 12   resources.
 13
 14   Therefore each board function gets a directory, which may in turn
 15   contain subdirectories.  Each slot resource is a file.  Unrecognized
 16   resources are empty files, since every resource ID requires a special
 17   case (e.g. if the resource ID implies a directory or block, then its
 18   value has to be interpreted as a slot ROM pointer etc.).
 19 */
 20
 21#include <linux/types.h>
 22#include <linux/kernel.h>
 23#include <linux/nubus.h>
 24#include <linux/proc_fs.h>
 25#include <linux/seq_file.h>
 26#include <linux/slab.h>
 27#include <linux/init.h>
 28#include <linux/module.h>
 29#include <linux/uaccess.h>
 30#include <asm/byteorder.h>
 31
 32/*
 33 * /proc/bus/nubus/devices stuff
 34 */
 35
 36static int
 37nubus_devices_proc_show(struct seq_file *m, void *v)
 38{
 39	struct nubus_rsrc *fres;
 40
 41	for_each_func_rsrc(fres)
 42		seq_printf(m, "%x\t%04x %04x %04x %04x\t%08lx\n",
 43			   fres->board->slot, fres->category, fres->type,
 44			   fres->dr_sw, fres->dr_hw, fres->board->slot_addr);
 45	return 0;
 46}
 47
 
 
 
 
 
 
 
 
 
 
 
 
 48static struct proc_dir_entry *proc_bus_nubus_dir;
 49
 50/*
 51 * /proc/bus/nubus/x/ stuff
 52 */
 53
 54struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board)
 55{
 56	char name[2];
 57
 58	if (!proc_bus_nubus_dir)
 59		return NULL;
 60	snprintf(name, sizeof(name), "%x", board->slot);
 61	return proc_mkdir(name, proc_bus_nubus_dir);
 62}
 63
 64/* The PDE private data for any directory under /proc/bus/nubus/x/
 65 * is the bytelanes value for the board in slot x.
 66 */
 67
 68struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir,
 69					       const struct nubus_dirent *ent,
 70					       struct nubus_board *board)
 71{
 72	char name[9];
 73	int lanes = board->lanes;
 74
 75	if (!procdir)
 76		return NULL;
 77	snprintf(name, sizeof(name), "%x", ent->type);
 78	return proc_mkdir_data(name, 0555, procdir, (void *)lanes);
 79}
 80
 81/* The PDE private data for a file under /proc/bus/nubus/x/ is a pointer to
 82 * an instance of the following structure, which gives the location and size
 83 * of the resource data in the slot ROM. For slot resources which hold only a
 84 * small integer, this integer value is stored directly and size is set to 0.
 85 * A NULL private data pointer indicates an unrecognized resource.
 86 */
 87
 88struct nubus_proc_pde_data {
 89	unsigned char *res_ptr;
 90	unsigned int res_size;
 91};
 92
 93static struct nubus_proc_pde_data *
 94nubus_proc_alloc_pde_data(unsigned char *ptr, unsigned int size)
 95{
 96	struct nubus_proc_pde_data *pde_data;
 97
 98	pde_data = kmalloc(sizeof(*pde_data), GFP_KERNEL);
 99	if (!pde_data)
100		return NULL;
101
102	pde_data->res_ptr = ptr;
103	pde_data->res_size = size;
104	return pde_data;
105}
106
107static int nubus_proc_rsrc_show(struct seq_file *m, void *v)
108{
109	struct inode *inode = m->private;
110	struct nubus_proc_pde_data *pde_data;
111
112	pde_data = PDE_DATA(inode);
113	if (!pde_data)
114		return 0;
115
116	if (pde_data->res_size > m->size)
117		return -EFBIG;
118
119	if (pde_data->res_size) {
120		int lanes = (int)proc_get_parent_data(inode);
121		struct nubus_dirent ent;
122
123		if (!lanes)
124			return 0;
125
126		ent.mask = lanes;
127		ent.base = pde_data->res_ptr;
128		ent.data = 0;
129		nubus_seq_write_rsrc_mem(m, &ent, pde_data->res_size);
130	} else {
131		unsigned int data = (unsigned int)pde_data->res_ptr;
132
133		seq_putc(m, data >> 16);
134		seq_putc(m, data >> 8);
135		seq_putc(m, data >> 0);
136	}
137	return 0;
138}
139
 
 
 
 
 
 
 
 
 
 
 
 
140void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
141			     const struct nubus_dirent *ent,
142			     unsigned int size)
143{
144	char name[9];
145	struct nubus_proc_pde_data *pde_data;
146
147	if (!procdir)
148		return;
149
150	snprintf(name, sizeof(name), "%x", ent->type);
151	if (size)
152		pde_data = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size);
153	else
154		pde_data = NULL;
155	proc_create_single_data(name, S_IFREG | 0444, procdir,
156			nubus_proc_rsrc_show, pde_data);
157}
158
159void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
160			 const struct nubus_dirent *ent)
161{
162	char name[9];
163	unsigned char *data = (unsigned char *)ent->data;
164
165	if (!procdir)
166		return;
167
168	snprintf(name, sizeof(name), "%x", ent->type);
169	proc_create_single_data(name, S_IFREG | 0444, procdir,
170			nubus_proc_rsrc_show,
171			nubus_proc_alloc_pde_data(data, 0));
172}
173
174/*
175 * /proc/nubus stuff
176 */
177
 
 
 
 
 
 
 
 
 
 
 
 
178void __init nubus_proc_init(void)
179{
180	proc_create_single("nubus", 0, NULL, nubus_proc_show);
181	proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
182	if (!proc_bus_nubus_dir)
183		return;
184	proc_create_single("devices", 0, proc_bus_nubus_dir,
185			nubus_devices_proc_show);
186}
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2/* drivers/nubus/proc.c: Proc FS interface for NuBus.
  3
  4   By David Huggins-Daines <dhd@debian.org>
  5
  6   Much code and many ideas from drivers/pci/proc.c:
  7   Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  8
  9   This is initially based on the Zorro and PCI interfaces.  However,
 10   it works somewhat differently.  The intent is to provide a
 11   structure in /proc analogous to the structure of the NuBus ROM
 12   resources.
 13
 14   Therefore each board function gets a directory, which may in turn
 15   contain subdirectories.  Each slot resource is a file.  Unrecognized
 16   resources are empty files, since every resource ID requires a special
 17   case (e.g. if the resource ID implies a directory or block, then its
 18   value has to be interpreted as a slot ROM pointer etc.).
 19 */
 20
 21#include <linux/types.h>
 22#include <linux/kernel.h>
 23#include <linux/nubus.h>
 24#include <linux/proc_fs.h>
 25#include <linux/seq_file.h>
 26#include <linux/slab.h>
 27#include <linux/init.h>
 28#include <linux/module.h>
 29#include <linux/uaccess.h>
 30#include <asm/byteorder.h>
 31
 32/*
 33 * /proc/bus/nubus/devices stuff
 34 */
 35
 36static int
 37nubus_devices_proc_show(struct seq_file *m, void *v)
 38{
 39	struct nubus_rsrc *fres;
 40
 41	for_each_func_rsrc(fres)
 42		seq_printf(m, "%x\t%04x %04x %04x %04x\t%08lx\n",
 43			   fres->board->slot, fres->category, fres->type,
 44			   fres->dr_sw, fres->dr_hw, fres->board->slot_addr);
 45	return 0;
 46}
 47
 48static int nubus_devices_proc_open(struct inode *inode, struct file *file)
 49{
 50	return single_open(file, nubus_devices_proc_show, NULL);
 51}
 52
 53static const struct file_operations nubus_devices_proc_fops = {
 54	.open		= nubus_devices_proc_open,
 55	.read		= seq_read,
 56	.llseek		= seq_lseek,
 57	.release	= single_release,
 58};
 59
 60static struct proc_dir_entry *proc_bus_nubus_dir;
 61
 62/*
 63 * /proc/bus/nubus/x/ stuff
 64 */
 65
 66struct proc_dir_entry *nubus_proc_add_board(struct nubus_board *board)
 67{
 68	char name[2];
 69
 70	if (!proc_bus_nubus_dir)
 71		return NULL;
 72	snprintf(name, sizeof(name), "%x", board->slot);
 73	return proc_mkdir(name, proc_bus_nubus_dir);
 74}
 75
 76/* The PDE private data for any directory under /proc/bus/nubus/x/
 77 * is the bytelanes value for the board in slot x.
 78 */
 79
 80struct proc_dir_entry *nubus_proc_add_rsrc_dir(struct proc_dir_entry *procdir,
 81					       const struct nubus_dirent *ent,
 82					       struct nubus_board *board)
 83{
 84	char name[9];
 85	int lanes = board->lanes;
 86
 87	if (!procdir)
 88		return NULL;
 89	snprintf(name, sizeof(name), "%x", ent->type);
 90	return proc_mkdir_data(name, 0555, procdir, (void *)lanes);
 91}
 92
 93/* The PDE private data for a file under /proc/bus/nubus/x/ is a pointer to
 94 * an instance of the following structure, which gives the location and size
 95 * of the resource data in the slot ROM. For slot resources which hold only a
 96 * small integer, this integer value is stored directly and size is set to 0.
 97 * A NULL private data pointer indicates an unrecognized resource.
 98 */
 99
100struct nubus_proc_pde_data {
101	unsigned char *res_ptr;
102	unsigned int res_size;
103};
104
105static struct nubus_proc_pde_data *
106nubus_proc_alloc_pde_data(unsigned char *ptr, unsigned int size)
107{
108	struct nubus_proc_pde_data *pde_data;
109
110	pde_data = kmalloc(sizeof(*pde_data), GFP_KERNEL);
111	if (!pde_data)
112		return NULL;
113
114	pde_data->res_ptr = ptr;
115	pde_data->res_size = size;
116	return pde_data;
117}
118
119static int nubus_proc_rsrc_show(struct seq_file *m, void *v)
120{
121	struct inode *inode = m->private;
122	struct nubus_proc_pde_data *pde_data;
123
124	pde_data = PDE_DATA(inode);
125	if (!pde_data)
126		return 0;
127
128	if (pde_data->res_size > m->size)
129		return -EFBIG;
130
131	if (pde_data->res_size) {
132		int lanes = (int)proc_get_parent_data(inode);
133		struct nubus_dirent ent;
134
135		if (!lanes)
136			return 0;
137
138		ent.mask = lanes;
139		ent.base = pde_data->res_ptr;
140		ent.data = 0;
141		nubus_seq_write_rsrc_mem(m, &ent, pde_data->res_size);
142	} else {
143		unsigned int data = (unsigned int)pde_data->res_ptr;
144
145		seq_putc(m, data >> 16);
146		seq_putc(m, data >> 8);
147		seq_putc(m, data >> 0);
148	}
149	return 0;
150}
151
152static int nubus_proc_rsrc_open(struct inode *inode, struct file *file)
153{
154	return single_open(file, nubus_proc_rsrc_show, inode);
155}
156
157static const struct file_operations nubus_proc_rsrc_fops = {
158	.open		= nubus_proc_rsrc_open,
159	.read		= seq_read,
160	.llseek		= seq_lseek,
161	.release	= single_release,
162};
163
164void nubus_proc_add_rsrc_mem(struct proc_dir_entry *procdir,
165			     const struct nubus_dirent *ent,
166			     unsigned int size)
167{
168	char name[9];
169	struct nubus_proc_pde_data *pde_data;
170
171	if (!procdir)
172		return;
173
174	snprintf(name, sizeof(name), "%x", ent->type);
175	if (size)
176		pde_data = nubus_proc_alloc_pde_data(nubus_dirptr(ent), size);
177	else
178		pde_data = NULL;
179	proc_create_data(name, S_IFREG | 0444, procdir,
180			 &nubus_proc_rsrc_fops, pde_data);
181}
182
183void nubus_proc_add_rsrc(struct proc_dir_entry *procdir,
184			 const struct nubus_dirent *ent)
185{
186	char name[9];
187	unsigned char *data = (unsigned char *)ent->data;
188
189	if (!procdir)
190		return;
191
192	snprintf(name, sizeof(name), "%x", ent->type);
193	proc_create_data(name, S_IFREG | 0444, procdir,
194			 &nubus_proc_rsrc_fops,
195			 nubus_proc_alloc_pde_data(data, 0));
196}
197
198/*
199 * /proc/nubus stuff
200 */
201
202static int nubus_proc_open(struct inode *inode, struct file *file)
203{
204	return single_open(file, nubus_proc_show, NULL);
205}
206
207static const struct file_operations nubus_proc_fops = {
208	.open		= nubus_proc_open,
209	.read		= seq_read,
210	.llseek		= seq_lseek,
211	.release	= single_release,
212};
213
214void __init nubus_proc_init(void)
215{
216	proc_create("nubus", 0, NULL, &nubus_proc_fops);
217	proc_bus_nubus_dir = proc_mkdir("bus/nubus", NULL);
218	if (!proc_bus_nubus_dir)
219		return;
220	proc_create("devices", 0, proc_bus_nubus_dir, &nubus_devices_proc_fops);
 
221}