2 * /proc/bus/pnp interface for Plug and Play devices
4 * Written by David Hinds, dahinds@users.sourceforge.net
5 * Modified by Thomas Hood
7 * The .../devices and .../<node> and .../boot/<node> files are
8 * utilized by the lspnp and setpnp utilities, supplied with the
10 * http://pcmcia-cs.sourceforge.net
12 * The .../escd file is utilized by the lsescd utility written by
14 * http://home.t-online.de/home/gunther.mayer/lsescd
16 * The .../legacy_device_resources file is not used yet.
18 * The other files are human-readable.
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/slab.h>
24 #include <linux/types.h>
25 #include <linux/proc_fs.h>
26 #include <linux/pnp.h>
27 #include <linux/seq_file.h>
28 #include <linux/init.h>
30 #include <asm/uaccess.h>
34 static struct proc_dir_entry
*proc_pnp
= NULL
;
35 static struct proc_dir_entry
*proc_pnp_boot
= NULL
;
37 static int pnpconfig_proc_show(struct seq_file
*m
, void *v
)
39 struct pnp_isa_config_struc pnps
;
41 if (pnp_bios_isapnp_config(&pnps
))
43 seq_printf(m
, "structure_revision %d\n"
45 "ISA_read_data_port 0x%x\n",
46 pnps
.revision
, pnps
.no_csns
, pnps
.isa_rd_data_port
);
50 static int pnpconfig_proc_open(struct inode
*inode
, struct file
*file
)
52 return single_open(file
, pnpconfig_proc_show
, NULL
);
55 static const struct file_operations pnpconfig_proc_fops
= {
57 .open
= pnpconfig_proc_open
,
60 .release
= single_release
,
63 static int escd_info_proc_show(struct seq_file
*m
, void *v
)
65 struct escd_info_struc escd
;
67 if (pnp_bios_escd_info(&escd
))
69 seq_printf(m
, "min_ESCD_write_size %d\n"
72 escd
.min_escd_write_size
,
73 escd
.escd_size
, escd
.nv_storage_base
);
77 static int escd_info_proc_open(struct inode
*inode
, struct file
*file
)
79 return single_open(file
, escd_info_proc_show
, NULL
);
82 static const struct file_operations escd_info_proc_fops
= {
84 .open
= escd_info_proc_open
,
87 .release
= single_release
,
90 #define MAX_SANE_ESCD_SIZE (32*1024)
91 static int escd_proc_show(struct seq_file
*m
, void *v
)
93 struct escd_info_struc escd
;
97 if (pnp_bios_escd_info(&escd
))
101 if (escd
.escd_size
> MAX_SANE_ESCD_SIZE
) {
103 "PnPBIOS: %s: ESCD size reported by BIOS escd_info call is too great\n", __func__
);
107 tmpbuf
= kzalloc(escd
.escd_size
, GFP_KERNEL
);
111 if (pnp_bios_read_escd(tmpbuf
, escd
.nv_storage_base
)) {
117 (unsigned char)(tmpbuf
[0]) + (unsigned char)(tmpbuf
[1]) * 256;
120 if (escd_size
> MAX_SANE_ESCD_SIZE
) {
121 printk(KERN_ERR
"PnPBIOS: %s: ESCD size reported by"
122 " BIOS read_escd call is too great\n", __func__
);
127 seq_write(m
, tmpbuf
, escd_size
);
132 static int escd_proc_open(struct inode
*inode
, struct file
*file
)
134 return single_open(file
, escd_proc_show
, NULL
);
137 static const struct file_operations escd_proc_fops
= {
138 .owner
= THIS_MODULE
,
139 .open
= escd_proc_open
,
142 .release
= single_release
,
145 static int pnp_legacyres_proc_show(struct seq_file
*m
, void *v
)
149 buf
= kmalloc(65536, GFP_KERNEL
);
152 if (pnp_bios_get_stat_res(buf
)) {
157 seq_write(m
, buf
, 65536);
162 static int pnp_legacyres_proc_open(struct inode
*inode
, struct file
*file
)
164 return single_open(file
, pnp_legacyres_proc_show
, NULL
);
167 static const struct file_operations pnp_legacyres_proc_fops
= {
168 .owner
= THIS_MODULE
,
169 .open
= pnp_legacyres_proc_open
,
172 .release
= single_release
,
175 static int pnp_devices_proc_show(struct seq_file
*m
, void *v
)
177 struct pnp_bios_node
*node
;
180 node
= kzalloc(node_info
.max_node_size
, GFP_KERNEL
);
184 for (nodenum
= 0; nodenum
< 0xff;) {
185 u8 thisnodenum
= nodenum
;
187 if (pnp_bios_get_dev_node(&nodenum
, PNPMODE_DYNAMIC
, node
))
189 seq_printf(m
, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
190 node
->handle
, node
->eisa_id
,
191 node
->type_code
[0], node
->type_code
[1],
192 node
->type_code
[2], node
->flags
);
193 if (nodenum
<= thisnodenum
) {
195 "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n",
196 "PnPBIOS: proc_read_devices:",
197 (unsigned int)nodenum
,
198 (unsigned int)thisnodenum
);
206 static int pnp_devices_proc_open(struct inode
*inode
, struct file
*file
)
208 return single_open(file
, pnp_devices_proc_show
, NULL
);
211 static const struct file_operations pnp_devices_proc_fops
= {
212 .owner
= THIS_MODULE
,
213 .open
= pnp_devices_proc_open
,
216 .release
= single_release
,
219 static int pnpbios_proc_show(struct seq_file
*m
, void *v
)
221 void *data
= m
->private;
222 struct pnp_bios_node
*node
;
223 int boot
= (long)data
>> 8;
224 u8 nodenum
= (long)data
;
227 node
= kzalloc(node_info
.max_node_size
, GFP_KERNEL
);
230 if (pnp_bios_get_dev_node(&nodenum
, boot
, node
)) {
234 len
= node
->size
- sizeof(struct pnp_bios_node
);
235 seq_write(m
, node
->data
, len
);
240 static int pnpbios_proc_open(struct inode
*inode
, struct file
*file
)
242 return single_open(file
, pnpbios_proc_show
, PDE(inode
)->data
);
245 static ssize_t
pnpbios_proc_write(struct file
*file
, const char __user
*buf
,
246 size_t count
, loff_t
*pos
)
248 void *data
= PDE(file
->f_path
.dentry
->d_inode
)->data
;
249 struct pnp_bios_node
*node
;
250 int boot
= (long)data
>> 8;
251 u8 nodenum
= (long)data
;
254 node
= kzalloc(node_info
.max_node_size
, GFP_KERNEL
);
257 if (pnp_bios_get_dev_node(&nodenum
, boot
, node
)) {
261 if (count
!= node
->size
- sizeof(struct pnp_bios_node
)) {
265 if (copy_from_user(node
->data
, buf
, count
)) {
269 if (pnp_bios_set_dev_node(node
->handle
, boot
, node
) != 0) {
279 static const struct file_operations pnpbios_proc_fops
= {
280 .owner
= THIS_MODULE
,
281 .open
= pnpbios_proc_open
,
284 .release
= single_release
,
285 .write
= pnpbios_proc_write
,
288 int pnpbios_interface_attach_device(struct pnp_bios_node
*node
)
292 sprintf(name
, "%02x", node
->handle
);
296 if (!pnpbios_dont_use_current_config
) {
297 proc_create_data(name
, 0644, proc_pnp
, &pnpbios_proc_fops
,
298 (void *)(long)(node
->handle
));
303 if (proc_create_data(name
, 0644, proc_pnp_boot
, &pnpbios_proc_fops
,
304 (void *)(long)(node
->handle
+ 0x100)))
310 * When this is called, pnpbios functions are assumed to
311 * work and the pnpbios_dont_use_current_config flag
312 * should already have been set to the appropriate value
314 int __init
pnpbios_proc_init(void)
316 proc_pnp
= proc_mkdir("bus/pnp", NULL
);
319 proc_pnp_boot
= proc_mkdir("boot", proc_pnp
);
322 proc_create("devices", 0, proc_pnp
, &pnp_devices_proc_fops
);
323 proc_create("configuration_info", 0, proc_pnp
, &pnpconfig_proc_fops
);
324 proc_create("escd_info", 0, proc_pnp
, &escd_info_proc_fops
);
325 proc_create("escd", S_IRUSR
, proc_pnp
, &escd_proc_fops
);
326 proc_create("legacy_device_resources", 0, proc_pnp
, &pnp_legacyres_proc_fops
);
331 void __exit
pnpbios_proc_exit(void)
339 for (i
= 0; i
< 0xff; i
++) {
340 sprintf(name
, "%02x", i
);
341 if (!pnpbios_dont_use_current_config
)
342 remove_proc_entry(name
, proc_pnp
);
343 remove_proc_entry(name
, proc_pnp_boot
);
345 remove_proc_entry("legacy_device_resources", proc_pnp
);
346 remove_proc_entry("escd", proc_pnp
);
347 remove_proc_entry("escd_info", proc_pnp
);
348 remove_proc_entry("configuration_info", proc_pnp
);
349 remove_proc_entry("devices", proc_pnp
);
350 remove_proc_entry("boot", proc_pnp
);
351 remove_proc_entry("bus/pnp", NULL
);