brintos

brintos / linux-shallow public Read only

0
0
Text · 12.3 KiB · 3880460 Raw
598 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Sysctl interface for parport devices.3 * 4 * Authors: David Campbell5 *          Tim Waugh <tim@cyberelk.demon.co.uk>6 *          Philip Blundell <philb@gnu.org>7 *          Andrea Arcangeli8 *          Riccardo Facchetti <fizban@tin.it>9 *10 * based on work by Grant Guenther <grant@torque.net>11 *              and Philip Blundell12 *13 * Cleaned up include files - Russell King <linux@arm.uk.linux.org>14 */15 16#include <linux/string.h>17#include <linux/init.h>18#include <linux/module.h>19#include <linux/errno.h>20#include <linux/kernel.h>21#include <linux/slab.h>22#include <linux/parport.h>23#include <linux/ctype.h>24#include <linux/sysctl.h>25#include <linux/device.h>26 27#include <linux/uaccess.h>28 29#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)30 31#define PARPORT_MIN_TIMESLICE_VALUE 1ul 32#define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)33#define PARPORT_MIN_SPINTIME_VALUE 134#define PARPORT_MAX_SPINTIME_VALUE 100035 36static int do_active_device(const struct ctl_table *table, int write,37		      void *result, size_t *lenp, loff_t *ppos)38{39	struct parport *port = (struct parport *)table->extra1;40	char buffer[256];41	struct pardevice *dev;42	int len = 0;43 44	if (write)		/* can't happen anyway */45		return -EACCES;46 47	if (*ppos) {48		*lenp = 0;49		return 0;50	}51	52	for (dev = port->devices; dev ; dev = dev->next) {53		if(dev == port->cad) {54			len += scnprintf(buffer, sizeof(buffer), "%s\n", dev->name);55		}56	}57 58	if(!len) {59		len += scnprintf(buffer, sizeof(buffer), "%s\n", "none");60	}61 62	if (len > *lenp)63		len = *lenp;64	else65		*lenp = len;66 67	*ppos += len;68	memcpy(result, buffer, len);69	return 0;70}71 72#ifdef CONFIG_PARPORT_128473static int do_autoprobe(const struct ctl_table *table, int write,74			void *result, size_t *lenp, loff_t *ppos)75{76	struct parport_device_info *info = table->extra2;77	const char *str;78	char buffer[256];79	int len = 0;80 81	if (write) /* permissions stop this */82		return -EACCES;83 84	if (*ppos) {85		*lenp = 0;86		return 0;87	}88	89	if ((str = info->class_name) != NULL)90		len += scnprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str);91 92	if ((str = info->model) != NULL)93		len += scnprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str);94 95	if ((str = info->mfr) != NULL)96		len += scnprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str);97 98	if ((str = info->description) != NULL)99		len += scnprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str);100 101	if ((str = info->cmdset) != NULL)102		len += scnprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str);103 104	if (len > *lenp)105		len = *lenp;106	else107		*lenp = len;108 109	*ppos += len;110 111	memcpy(result, buffer, len);112	return 0;113}114#endif /* IEEE1284.3 support. */115 116static int do_hardware_base_addr(const struct ctl_table *table, int write,117				 void *result, size_t *lenp, loff_t *ppos)118{119	struct parport *port = (struct parport *)table->extra1;120	char buffer[64];121	int len = 0;122 123	if (*ppos) {124		*lenp = 0;125		return 0;126	}127 128	if (write) /* permissions prevent this anyway */129		return -EACCES;130 131	len += scnprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi);132 133	if (len > *lenp)134		len = *lenp;135	else136		*lenp = len;137 138	*ppos += len;139	memcpy(result, buffer, len);140	return 0;141}142 143static int do_hardware_irq(const struct ctl_table *table, int write,144			   void *result, size_t *lenp, loff_t *ppos)145{146	struct parport *port = (struct parport *)table->extra1;147	char buffer[20];148	int len = 0;149 150	if (*ppos) {151		*lenp = 0;152		return 0;153	}154 155	if (write) /* permissions prevent this anyway */156		return -EACCES;157 158	len += scnprintf (buffer, sizeof(buffer), "%d\n", port->irq);159 160	if (len > *lenp)161		len = *lenp;162	else163		*lenp = len;164 165	*ppos += len;166	memcpy(result, buffer, len);167	return 0;168}169 170static int do_hardware_dma(const struct ctl_table *table, int write,171			   void *result, size_t *lenp, loff_t *ppos)172{173	struct parport *port = (struct parport *)table->extra1;174	char buffer[20];175	int len = 0;176 177	if (*ppos) {178		*lenp = 0;179		return 0;180	}181 182	if (write) /* permissions prevent this anyway */183		return -EACCES;184 185	len += scnprintf (buffer, sizeof(buffer), "%d\n", port->dma);186 187	if (len > *lenp)188		len = *lenp;189	else190		*lenp = len;191 192	*ppos += len;193	memcpy(result, buffer, len);194	return 0;195}196 197static int do_hardware_modes(const struct ctl_table *table, int write,198			     void *result, size_t *lenp, loff_t *ppos)199{200	struct parport *port = (struct parport *)table->extra1;201	char buffer[40];202	int len = 0;203 204	if (*ppos) {205		*lenp = 0;206		return 0;207	}208 209	if (write) /* permissions prevent this anyway */210		return -EACCES;211 212	{213#define printmode(x)							\214do {									\215	if (port->modes & PARPORT_MODE_##x)				\216		len += scnprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \217} while (0)218		int f = 0;219		printmode(PCSPP);220		printmode(TRISTATE);221		printmode(COMPAT);222		printmode(EPP);223		printmode(ECP);224		printmode(DMA);225#undef printmode226	}227	buffer[len++] = '\n';228 229	if (len > *lenp)230		len = *lenp;231	else232		*lenp = len;233 234	*ppos += len;235	memcpy(result, buffer, len);236	return 0;237}238 239static const unsigned long parport_min_timeslice_value =240PARPORT_MIN_TIMESLICE_VALUE;241 242static const unsigned long parport_max_timeslice_value =243PARPORT_MAX_TIMESLICE_VALUE;244 245static const  int parport_min_spintime_value =246PARPORT_MIN_SPINTIME_VALUE;247 248static const int parport_max_spintime_value =249PARPORT_MAX_SPINTIME_VALUE;250 251 252struct parport_sysctl_table {253	struct ctl_table_header *port_header;254	struct ctl_table_header *devices_header;255#ifdef CONFIG_PARPORT_1284256	struct ctl_table vars[10];257#else258	struct ctl_table vars[5];259#endif /* IEEE 1284 support */260	struct ctl_table device_dir[1];261};262 263static const struct parport_sysctl_table parport_sysctl_template = {264	.port_header = NULL,265	.devices_header = NULL,266	{267		{268			.procname	= "spintime",269			.data		= NULL,270			.maxlen		= sizeof(int),271			.mode		= 0644,272			.proc_handler	= proc_dointvec_minmax,273			.extra1		= (void*) &parport_min_spintime_value,274			.extra2		= (void*) &parport_max_spintime_value275		},276		{277			.procname	= "base-addr",278			.data		= NULL,279			.maxlen		= 0,280			.mode		= 0444,281			.proc_handler	= do_hardware_base_addr282		},283		{284			.procname	= "irq",285			.data		= NULL,286			.maxlen		= 0,287			.mode		= 0444,288			.proc_handler	= do_hardware_irq289		},290		{291			.procname	= "dma",292			.data		= NULL,293			.maxlen		= 0,294			.mode		= 0444,295			.proc_handler	= do_hardware_dma296		},297		{298			.procname	= "modes",299			.data		= NULL,300			.maxlen		= 0,301			.mode		= 0444,302			.proc_handler	= do_hardware_modes303		},304#ifdef CONFIG_PARPORT_1284305		{306			.procname	= "autoprobe",307			.data		= NULL,308			.maxlen		= 0,309			.mode		= 0444,310			.proc_handler	= do_autoprobe311		},312		{313			.procname	= "autoprobe0",314			.data		= NULL,315			.maxlen		= 0,316			.mode		= 0444,317			.proc_handler	= do_autoprobe318		},319		{320			.procname	= "autoprobe1",321			.data		= NULL,322			.maxlen		= 0,323			.mode		= 0444,324			.proc_handler	= do_autoprobe325		},326		{327			.procname	= "autoprobe2",328			.data		= NULL,329			.maxlen		= 0,330			.mode		= 0444,331			.proc_handler	= do_autoprobe332		},333		{334			.procname	= "autoprobe3",335			.data		= NULL,336			.maxlen		= 0,337			.mode		= 0444,338			.proc_handler	= do_autoprobe339		},340#endif /* IEEE 1284 support */341	},342	{343		{344			.procname	= "active",345			.data		= NULL,346			.maxlen		= 0,347			.mode		= 0444,348			.proc_handler	= do_active_device349		},350	},351};352 353struct parport_device_sysctl_table354{355	struct ctl_table_header *sysctl_header;356	struct ctl_table vars[1];357	struct ctl_table device_dir[1];358};359 360static const struct parport_device_sysctl_table361parport_device_sysctl_template = {362	.sysctl_header = NULL,363	{364		{365			.procname 	= "timeslice",366			.data		= NULL,367			.maxlen		= sizeof(unsigned long),368			.mode		= 0644,369			.proc_handler	= proc_doulongvec_ms_jiffies_minmax,370			.extra1		= (void*) &parport_min_timeslice_value,371			.extra2		= (void*) &parport_max_timeslice_value372		},373	},374	{375		{376			.procname	= NULL,377			.data		= NULL,378			.maxlen		= 0,379			.mode		= 0555,380		},381	}382};383 384struct parport_default_sysctl_table385{386	struct ctl_table_header *sysctl_header;387	struct ctl_table vars[2];388};389 390static struct parport_default_sysctl_table391parport_default_sysctl_table = {392	.sysctl_header	= NULL,393	{394		{395			.procname	= "timeslice",396			.data		= &parport_default_timeslice,397			.maxlen		= sizeof(parport_default_timeslice),398			.mode		= 0644,399			.proc_handler	= proc_doulongvec_ms_jiffies_minmax,400			.extra1		= (void*) &parport_min_timeslice_value,401			.extra2		= (void*) &parport_max_timeslice_value402		},403		{404			.procname	= "spintime",405			.data		= &parport_default_spintime,406			.maxlen		= sizeof(parport_default_spintime),407			.mode		= 0644,408			.proc_handler	= proc_dointvec_minmax,409			.extra1		= (void*) &parport_min_spintime_value,410			.extra2		= (void*) &parport_max_spintime_value411		},412	}413};414 415int parport_proc_register(struct parport *port)416{417	struct parport_sysctl_table *t;418	char *tmp_dir_path;419	int i, err = 0;420 421	t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);422	if (t == NULL)423		return -ENOMEM;424 425	t->device_dir[0].extra1 = port;426 427	t->vars[0].data = &port->spintime;428	for (i = 0; i < 5; i++) {429		t->vars[i].extra1 = port;430#ifdef CONFIG_PARPORT_1284431		t->vars[5 + i].extra2 = &port->probe_info[i];432#endif /* IEEE 1284 support */433	}434 435	tmp_dir_path = kasprintf(GFP_KERNEL, "dev/parport/%s/devices", port->name);436	if (!tmp_dir_path) {437		err = -ENOMEM;438		goto exit_free_t;439	}440 441	t->devices_header = register_sysctl(tmp_dir_path, t->device_dir);442	if (t->devices_header == NULL) {443		err = -ENOENT;444		goto  exit_free_tmp_dir_path;445	}446 447	kfree(tmp_dir_path);448 449	tmp_dir_path = kasprintf(GFP_KERNEL, "dev/parport/%s", port->name);450	if (!tmp_dir_path) {451		err = -ENOMEM;452		goto unregister_devices_h;453	}454 455	t->port_header = register_sysctl(tmp_dir_path, t->vars);456	if (t->port_header == NULL) {457		err = -ENOENT;458		goto unregister_devices_h;459	}460 461	port->sysctl_table = t;462 463	kfree(tmp_dir_path);464	return 0;465 466unregister_devices_h:467	unregister_sysctl_table(t->devices_header);468 469exit_free_tmp_dir_path:470	kfree(tmp_dir_path);471 472exit_free_t:473	kfree(t);474	return err;475}476 477int parport_proc_unregister(struct parport *port)478{479	if (port->sysctl_table) {480		struct parport_sysctl_table *t = port->sysctl_table;481		port->sysctl_table = NULL;482		unregister_sysctl_table(t->devices_header);483		unregister_sysctl_table(t->port_header);484		kfree(t);485	}486	return 0;487}488 489int parport_device_proc_register(struct pardevice *device)490{491	struct parport_device_sysctl_table *t;492	struct parport * port = device->port;493	char *tmp_dir_path;494	int err = 0;495	496	t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);497	if (t == NULL)498		return -ENOMEM;499 500	/* Allocate a buffer for two paths: dev/parport/PORT/devices/DEVICE. */501	tmp_dir_path = kasprintf(GFP_KERNEL, "dev/parport/%s/devices/%s", port->name, device->name);502	if (!tmp_dir_path) {503		err = -ENOMEM;504		goto exit_free_t;505	}506 507	t->vars[0].data = &device->timeslice;508 509	t->sysctl_header = register_sysctl(tmp_dir_path, t->vars);510	if (t->sysctl_header == NULL) {511		kfree(t);512		t = NULL;513	}514	device->sysctl_table = t;515 516	kfree(tmp_dir_path);517	return 0;518 519exit_free_t:520	kfree(t);521 522	return err;523}524 525int parport_device_proc_unregister(struct pardevice *device)526{527	if (device->sysctl_table) {528		struct parport_device_sysctl_table *t = device->sysctl_table;529		device->sysctl_table = NULL;530		unregister_sysctl_table(t->sysctl_header);531		kfree(t);532	}533	return 0;534}535 536static int __init parport_default_proc_register(void)537{538	int ret;539 540	parport_default_sysctl_table.sysctl_header =541		register_sysctl("dev/parport/default", parport_default_sysctl_table.vars);542	if (!parport_default_sysctl_table.sysctl_header)543		return -ENOMEM;544	ret = parport_bus_init();545	if (ret) {546		unregister_sysctl_table(parport_default_sysctl_table.547					sysctl_header);548		return ret;549	}550	return 0;551}552 553static void __exit parport_default_proc_unregister(void)554{555	if (parport_default_sysctl_table.sysctl_header) {556		unregister_sysctl_table(parport_default_sysctl_table.557					sysctl_header);558		parport_default_sysctl_table.sysctl_header = NULL;559	}560	parport_bus_exit();561}562 563#else /* no sysctl or no procfs*/564 565int parport_proc_register(struct parport *pp)566{567	return 0;568}569 570int parport_proc_unregister(struct parport *pp)571{572	return 0;573}574 575int parport_device_proc_register(struct pardevice *device)576{577	return 0;578}579 580int parport_device_proc_unregister(struct pardevice *device)581{582	return 0;583}584 585static int __init parport_default_proc_register (void)586{587	return parport_bus_init();588}589 590static void __exit parport_default_proc_unregister (void)591{592	parport_bus_exit();593}594#endif595 596subsys_initcall(parport_default_proc_register)597module_exit(parport_default_proc_unregister)598