18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Sysctl interface for parport devices. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Authors: David Campbell 58c2ecf20Sopenharmony_ci * Tim Waugh <tim@cyberelk.demon.co.uk> 68c2ecf20Sopenharmony_ci * Philip Blundell <philb@gnu.org> 78c2ecf20Sopenharmony_ci * Andrea Arcangeli 88c2ecf20Sopenharmony_ci * Riccardo Facchetti <fizban@tin.it> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * based on work by Grant Guenther <grant@torque.net> 118c2ecf20Sopenharmony_ci * and Philip Blundell 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * Cleaned up include files - Russell King <linux@arm.uk.linux.org> 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/string.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/errno.h> 208c2ecf20Sopenharmony_ci#include <linux/kernel.h> 218c2ecf20Sopenharmony_ci#include <linux/slab.h> 228c2ecf20Sopenharmony_ci#include <linux/parport.h> 238c2ecf20Sopenharmony_ci#include <linux/ctype.h> 248c2ecf20Sopenharmony_ci#include <linux/sysctl.h> 258c2ecf20Sopenharmony_ci#include <linux/device.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define PARPORT_MIN_TIMESLICE_VALUE 1ul 328c2ecf20Sopenharmony_ci#define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ) 338c2ecf20Sopenharmony_ci#define PARPORT_MIN_SPINTIME_VALUE 1 348c2ecf20Sopenharmony_ci#define PARPORT_MAX_SPINTIME_VALUE 1000 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic int do_active_device(struct ctl_table *table, int write, 378c2ecf20Sopenharmony_ci void *result, size_t *lenp, loff_t *ppos) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci struct parport *port = (struct parport *)table->extra1; 408c2ecf20Sopenharmony_ci char buffer[256]; 418c2ecf20Sopenharmony_ci struct pardevice *dev; 428c2ecf20Sopenharmony_ci int len = 0; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (write) /* can't happen anyway */ 458c2ecf20Sopenharmony_ci return -EACCES; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci if (*ppos) { 488c2ecf20Sopenharmony_ci *lenp = 0; 498c2ecf20Sopenharmony_ci return 0; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci for (dev = port->devices; dev ; dev = dev->next) { 538c2ecf20Sopenharmony_ci if(dev == port->cad) { 548c2ecf20Sopenharmony_ci len += sprintf(buffer, "%s\n", dev->name); 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if(!len) { 598c2ecf20Sopenharmony_ci len += sprintf(buffer, "%s\n", "none"); 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (len > *lenp) 638c2ecf20Sopenharmony_ci len = *lenp; 648c2ecf20Sopenharmony_ci else 658c2ecf20Sopenharmony_ci *lenp = len; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci *ppos += len; 688c2ecf20Sopenharmony_ci memcpy(result, buffer, len); 698c2ecf20Sopenharmony_ci return 0; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#ifdef CONFIG_PARPORT_1284 738c2ecf20Sopenharmony_cistatic int do_autoprobe(struct ctl_table *table, int write, 748c2ecf20Sopenharmony_ci void *result, size_t *lenp, loff_t *ppos) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct parport_device_info *info = table->extra2; 778c2ecf20Sopenharmony_ci const char *str; 788c2ecf20Sopenharmony_ci char buffer[256]; 798c2ecf20Sopenharmony_ci int len = 0; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (write) /* permissions stop this */ 828c2ecf20Sopenharmony_ci return -EACCES; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (*ppos) { 858c2ecf20Sopenharmony_ci *lenp = 0; 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if ((str = info->class_name) != NULL) 908c2ecf20Sopenharmony_ci len += sprintf (buffer + len, "CLASS:%s;\n", str); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci if ((str = info->model) != NULL) 938c2ecf20Sopenharmony_ci len += sprintf (buffer + len, "MODEL:%s;\n", str); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if ((str = info->mfr) != NULL) 968c2ecf20Sopenharmony_ci len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if ((str = info->description) != NULL) 998c2ecf20Sopenharmony_ci len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci if ((str = info->cmdset) != NULL) 1028c2ecf20Sopenharmony_ci len += sprintf (buffer + len, "COMMAND SET:%s;\n", str); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (len > *lenp) 1058c2ecf20Sopenharmony_ci len = *lenp; 1068c2ecf20Sopenharmony_ci else 1078c2ecf20Sopenharmony_ci *lenp = len; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci *ppos += len; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci memcpy(result, buffer, len); 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci#endif /* IEEE1284.3 support. */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic int do_hardware_base_addr(struct ctl_table *table, int write, 1178c2ecf20Sopenharmony_ci void *result, size_t *lenp, loff_t *ppos) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci struct parport *port = (struct parport *)table->extra1; 1208c2ecf20Sopenharmony_ci char buffer[20]; 1218c2ecf20Sopenharmony_ci int len = 0; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (*ppos) { 1248c2ecf20Sopenharmony_ci *lenp = 0; 1258c2ecf20Sopenharmony_ci return 0; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (write) /* permissions prevent this anyway */ 1298c2ecf20Sopenharmony_ci return -EACCES; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (len > *lenp) 1348c2ecf20Sopenharmony_ci len = *lenp; 1358c2ecf20Sopenharmony_ci else 1368c2ecf20Sopenharmony_ci *lenp = len; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci *ppos += len; 1398c2ecf20Sopenharmony_ci memcpy(result, buffer, len); 1408c2ecf20Sopenharmony_ci return 0; 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic int do_hardware_irq(struct ctl_table *table, int write, 1448c2ecf20Sopenharmony_ci void *result, size_t *lenp, loff_t *ppos) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci struct parport *port = (struct parport *)table->extra1; 1478c2ecf20Sopenharmony_ci char buffer[20]; 1488c2ecf20Sopenharmony_ci int len = 0; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (*ppos) { 1518c2ecf20Sopenharmony_ci *lenp = 0; 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci } 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (write) /* permissions prevent this anyway */ 1568c2ecf20Sopenharmony_ci return -EACCES; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci len += sprintf (buffer, "%d\n", port->irq); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (len > *lenp) 1618c2ecf20Sopenharmony_ci len = *lenp; 1628c2ecf20Sopenharmony_ci else 1638c2ecf20Sopenharmony_ci *lenp = len; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci *ppos += len; 1668c2ecf20Sopenharmony_ci memcpy(result, buffer, len); 1678c2ecf20Sopenharmony_ci return 0; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic int do_hardware_dma(struct ctl_table *table, int write, 1718c2ecf20Sopenharmony_ci void *result, size_t *lenp, loff_t *ppos) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci struct parport *port = (struct parport *)table->extra1; 1748c2ecf20Sopenharmony_ci char buffer[20]; 1758c2ecf20Sopenharmony_ci int len = 0; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci if (*ppos) { 1788c2ecf20Sopenharmony_ci *lenp = 0; 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (write) /* permissions prevent this anyway */ 1838c2ecf20Sopenharmony_ci return -EACCES; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci len += sprintf (buffer, "%d\n", port->dma); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (len > *lenp) 1888c2ecf20Sopenharmony_ci len = *lenp; 1898c2ecf20Sopenharmony_ci else 1908c2ecf20Sopenharmony_ci *lenp = len; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci *ppos += len; 1938c2ecf20Sopenharmony_ci memcpy(result, buffer, len); 1948c2ecf20Sopenharmony_ci return 0; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int do_hardware_modes(struct ctl_table *table, int write, 1988c2ecf20Sopenharmony_ci void *result, size_t *lenp, loff_t *ppos) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct parport *port = (struct parport *)table->extra1; 2018c2ecf20Sopenharmony_ci char buffer[40]; 2028c2ecf20Sopenharmony_ci int len = 0; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (*ppos) { 2058c2ecf20Sopenharmony_ci *lenp = 0; 2068c2ecf20Sopenharmony_ci return 0; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (write) /* permissions prevent this anyway */ 2108c2ecf20Sopenharmony_ci return -EACCES; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci { 2138c2ecf20Sopenharmony_ci#define printmode(x) \ 2148c2ecf20Sopenharmony_cido { \ 2158c2ecf20Sopenharmony_ci if (port->modes & PARPORT_MODE_##x) \ 2168c2ecf20Sopenharmony_ci len += sprintf(buffer + len, "%s%s", f++ ? "," : "", #x); \ 2178c2ecf20Sopenharmony_ci} while (0) 2188c2ecf20Sopenharmony_ci int f = 0; 2198c2ecf20Sopenharmony_ci printmode(PCSPP); 2208c2ecf20Sopenharmony_ci printmode(TRISTATE); 2218c2ecf20Sopenharmony_ci printmode(COMPAT); 2228c2ecf20Sopenharmony_ci printmode(EPP); 2238c2ecf20Sopenharmony_ci printmode(ECP); 2248c2ecf20Sopenharmony_ci printmode(DMA); 2258c2ecf20Sopenharmony_ci#undef printmode 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci buffer[len++] = '\n'; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (len > *lenp) 2308c2ecf20Sopenharmony_ci len = *lenp; 2318c2ecf20Sopenharmony_ci else 2328c2ecf20Sopenharmony_ci *lenp = len; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci *ppos += len; 2358c2ecf20Sopenharmony_ci memcpy(result, buffer, len); 2368c2ecf20Sopenharmony_ci return 0; 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD } 2408c2ecf20Sopenharmony_ci#define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \ 2418c2ecf20Sopenharmony_ci .mode = 0555, .child = CHILD } 2428c2ecf20Sopenharmony_ci#define PARPORT_DEV_DIR(CHILD) { .procname = "dev", .mode = 0555, .child = CHILD } 2438c2ecf20Sopenharmony_ci#define PARPORT_DEVICES_ROOT_DIR { .procname = "devices", \ 2448c2ecf20Sopenharmony_ci .mode = 0555, .child = NULL } 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic const unsigned long parport_min_timeslice_value = 2478c2ecf20Sopenharmony_ciPARPORT_MIN_TIMESLICE_VALUE; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic const unsigned long parport_max_timeslice_value = 2508c2ecf20Sopenharmony_ciPARPORT_MAX_TIMESLICE_VALUE; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistatic const int parport_min_spintime_value = 2538c2ecf20Sopenharmony_ciPARPORT_MIN_SPINTIME_VALUE; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic const int parport_max_spintime_value = 2568c2ecf20Sopenharmony_ciPARPORT_MAX_SPINTIME_VALUE; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistruct parport_sysctl_table { 2608c2ecf20Sopenharmony_ci struct ctl_table_header *sysctl_header; 2618c2ecf20Sopenharmony_ci struct ctl_table vars[12]; 2628c2ecf20Sopenharmony_ci struct ctl_table device_dir[2]; 2638c2ecf20Sopenharmony_ci struct ctl_table port_dir[2]; 2648c2ecf20Sopenharmony_ci struct ctl_table parport_dir[2]; 2658c2ecf20Sopenharmony_ci struct ctl_table dev_dir[2]; 2668c2ecf20Sopenharmony_ci}; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic const struct parport_sysctl_table parport_sysctl_template = { 2698c2ecf20Sopenharmony_ci .sysctl_header = NULL, 2708c2ecf20Sopenharmony_ci { 2718c2ecf20Sopenharmony_ci { 2728c2ecf20Sopenharmony_ci .procname = "spintime", 2738c2ecf20Sopenharmony_ci .data = NULL, 2748c2ecf20Sopenharmony_ci .maxlen = sizeof(int), 2758c2ecf20Sopenharmony_ci .mode = 0644, 2768c2ecf20Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 2778c2ecf20Sopenharmony_ci .extra1 = (void*) &parport_min_spintime_value, 2788c2ecf20Sopenharmony_ci .extra2 = (void*) &parport_max_spintime_value 2798c2ecf20Sopenharmony_ci }, 2808c2ecf20Sopenharmony_ci { 2818c2ecf20Sopenharmony_ci .procname = "base-addr", 2828c2ecf20Sopenharmony_ci .data = NULL, 2838c2ecf20Sopenharmony_ci .maxlen = 0, 2848c2ecf20Sopenharmony_ci .mode = 0444, 2858c2ecf20Sopenharmony_ci .proc_handler = do_hardware_base_addr 2868c2ecf20Sopenharmony_ci }, 2878c2ecf20Sopenharmony_ci { 2888c2ecf20Sopenharmony_ci .procname = "irq", 2898c2ecf20Sopenharmony_ci .data = NULL, 2908c2ecf20Sopenharmony_ci .maxlen = 0, 2918c2ecf20Sopenharmony_ci .mode = 0444, 2928c2ecf20Sopenharmony_ci .proc_handler = do_hardware_irq 2938c2ecf20Sopenharmony_ci }, 2948c2ecf20Sopenharmony_ci { 2958c2ecf20Sopenharmony_ci .procname = "dma", 2968c2ecf20Sopenharmony_ci .data = NULL, 2978c2ecf20Sopenharmony_ci .maxlen = 0, 2988c2ecf20Sopenharmony_ci .mode = 0444, 2998c2ecf20Sopenharmony_ci .proc_handler = do_hardware_dma 3008c2ecf20Sopenharmony_ci }, 3018c2ecf20Sopenharmony_ci { 3028c2ecf20Sopenharmony_ci .procname = "modes", 3038c2ecf20Sopenharmony_ci .data = NULL, 3048c2ecf20Sopenharmony_ci .maxlen = 0, 3058c2ecf20Sopenharmony_ci .mode = 0444, 3068c2ecf20Sopenharmony_ci .proc_handler = do_hardware_modes 3078c2ecf20Sopenharmony_ci }, 3088c2ecf20Sopenharmony_ci PARPORT_DEVICES_ROOT_DIR, 3098c2ecf20Sopenharmony_ci#ifdef CONFIG_PARPORT_1284 3108c2ecf20Sopenharmony_ci { 3118c2ecf20Sopenharmony_ci .procname = "autoprobe", 3128c2ecf20Sopenharmony_ci .data = NULL, 3138c2ecf20Sopenharmony_ci .maxlen = 0, 3148c2ecf20Sopenharmony_ci .mode = 0444, 3158c2ecf20Sopenharmony_ci .proc_handler = do_autoprobe 3168c2ecf20Sopenharmony_ci }, 3178c2ecf20Sopenharmony_ci { 3188c2ecf20Sopenharmony_ci .procname = "autoprobe0", 3198c2ecf20Sopenharmony_ci .data = NULL, 3208c2ecf20Sopenharmony_ci .maxlen = 0, 3218c2ecf20Sopenharmony_ci .mode = 0444, 3228c2ecf20Sopenharmony_ci .proc_handler = do_autoprobe 3238c2ecf20Sopenharmony_ci }, 3248c2ecf20Sopenharmony_ci { 3258c2ecf20Sopenharmony_ci .procname = "autoprobe1", 3268c2ecf20Sopenharmony_ci .data = NULL, 3278c2ecf20Sopenharmony_ci .maxlen = 0, 3288c2ecf20Sopenharmony_ci .mode = 0444, 3298c2ecf20Sopenharmony_ci .proc_handler = do_autoprobe 3308c2ecf20Sopenharmony_ci }, 3318c2ecf20Sopenharmony_ci { 3328c2ecf20Sopenharmony_ci .procname = "autoprobe2", 3338c2ecf20Sopenharmony_ci .data = NULL, 3348c2ecf20Sopenharmony_ci .maxlen = 0, 3358c2ecf20Sopenharmony_ci .mode = 0444, 3368c2ecf20Sopenharmony_ci .proc_handler = do_autoprobe 3378c2ecf20Sopenharmony_ci }, 3388c2ecf20Sopenharmony_ci { 3398c2ecf20Sopenharmony_ci .procname = "autoprobe3", 3408c2ecf20Sopenharmony_ci .data = NULL, 3418c2ecf20Sopenharmony_ci .maxlen = 0, 3428c2ecf20Sopenharmony_ci .mode = 0444, 3438c2ecf20Sopenharmony_ci .proc_handler = do_autoprobe 3448c2ecf20Sopenharmony_ci }, 3458c2ecf20Sopenharmony_ci#endif /* IEEE 1284 support */ 3468c2ecf20Sopenharmony_ci {} 3478c2ecf20Sopenharmony_ci }, 3488c2ecf20Sopenharmony_ci { 3498c2ecf20Sopenharmony_ci { 3508c2ecf20Sopenharmony_ci .procname = "active", 3518c2ecf20Sopenharmony_ci .data = NULL, 3528c2ecf20Sopenharmony_ci .maxlen = 0, 3538c2ecf20Sopenharmony_ci .mode = 0444, 3548c2ecf20Sopenharmony_ci .proc_handler = do_active_device 3558c2ecf20Sopenharmony_ci }, 3568c2ecf20Sopenharmony_ci {} 3578c2ecf20Sopenharmony_ci }, 3588c2ecf20Sopenharmony_ci { 3598c2ecf20Sopenharmony_ci PARPORT_PORT_DIR(NULL), 3608c2ecf20Sopenharmony_ci {} 3618c2ecf20Sopenharmony_ci }, 3628c2ecf20Sopenharmony_ci { 3638c2ecf20Sopenharmony_ci PARPORT_PARPORT_DIR(NULL), 3648c2ecf20Sopenharmony_ci {} 3658c2ecf20Sopenharmony_ci }, 3668c2ecf20Sopenharmony_ci { 3678c2ecf20Sopenharmony_ci PARPORT_DEV_DIR(NULL), 3688c2ecf20Sopenharmony_ci {} 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci}; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistruct parport_device_sysctl_table 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci struct ctl_table_header *sysctl_header; 3758c2ecf20Sopenharmony_ci struct ctl_table vars[2]; 3768c2ecf20Sopenharmony_ci struct ctl_table device_dir[2]; 3778c2ecf20Sopenharmony_ci struct ctl_table devices_root_dir[2]; 3788c2ecf20Sopenharmony_ci struct ctl_table port_dir[2]; 3798c2ecf20Sopenharmony_ci struct ctl_table parport_dir[2]; 3808c2ecf20Sopenharmony_ci struct ctl_table dev_dir[2]; 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic const struct parport_device_sysctl_table 3848c2ecf20Sopenharmony_ciparport_device_sysctl_template = { 3858c2ecf20Sopenharmony_ci .sysctl_header = NULL, 3868c2ecf20Sopenharmony_ci { 3878c2ecf20Sopenharmony_ci { 3888c2ecf20Sopenharmony_ci .procname = "timeslice", 3898c2ecf20Sopenharmony_ci .data = NULL, 3908c2ecf20Sopenharmony_ci .maxlen = sizeof(unsigned long), 3918c2ecf20Sopenharmony_ci .mode = 0644, 3928c2ecf20Sopenharmony_ci .proc_handler = proc_doulongvec_ms_jiffies_minmax, 3938c2ecf20Sopenharmony_ci .extra1 = (void*) &parport_min_timeslice_value, 3948c2ecf20Sopenharmony_ci .extra2 = (void*) &parport_max_timeslice_value 3958c2ecf20Sopenharmony_ci }, 3968c2ecf20Sopenharmony_ci }, 3978c2ecf20Sopenharmony_ci { 3988c2ecf20Sopenharmony_ci { 3998c2ecf20Sopenharmony_ci .procname = NULL, 4008c2ecf20Sopenharmony_ci .data = NULL, 4018c2ecf20Sopenharmony_ci .maxlen = 0, 4028c2ecf20Sopenharmony_ci .mode = 0555, 4038c2ecf20Sopenharmony_ci .child = NULL 4048c2ecf20Sopenharmony_ci }, 4058c2ecf20Sopenharmony_ci {} 4068c2ecf20Sopenharmony_ci }, 4078c2ecf20Sopenharmony_ci { 4088c2ecf20Sopenharmony_ci PARPORT_DEVICES_ROOT_DIR, 4098c2ecf20Sopenharmony_ci {} 4108c2ecf20Sopenharmony_ci }, 4118c2ecf20Sopenharmony_ci { 4128c2ecf20Sopenharmony_ci PARPORT_PORT_DIR(NULL), 4138c2ecf20Sopenharmony_ci {} 4148c2ecf20Sopenharmony_ci }, 4158c2ecf20Sopenharmony_ci { 4168c2ecf20Sopenharmony_ci PARPORT_PARPORT_DIR(NULL), 4178c2ecf20Sopenharmony_ci {} 4188c2ecf20Sopenharmony_ci }, 4198c2ecf20Sopenharmony_ci { 4208c2ecf20Sopenharmony_ci PARPORT_DEV_DIR(NULL), 4218c2ecf20Sopenharmony_ci {} 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci}; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistruct parport_default_sysctl_table 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci struct ctl_table_header *sysctl_header; 4288c2ecf20Sopenharmony_ci struct ctl_table vars[3]; 4298c2ecf20Sopenharmony_ci struct ctl_table default_dir[2]; 4308c2ecf20Sopenharmony_ci struct ctl_table parport_dir[2]; 4318c2ecf20Sopenharmony_ci struct ctl_table dev_dir[2]; 4328c2ecf20Sopenharmony_ci}; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic struct parport_default_sysctl_table 4358c2ecf20Sopenharmony_ciparport_default_sysctl_table = { 4368c2ecf20Sopenharmony_ci .sysctl_header = NULL, 4378c2ecf20Sopenharmony_ci { 4388c2ecf20Sopenharmony_ci { 4398c2ecf20Sopenharmony_ci .procname = "timeslice", 4408c2ecf20Sopenharmony_ci .data = &parport_default_timeslice, 4418c2ecf20Sopenharmony_ci .maxlen = sizeof(parport_default_timeslice), 4428c2ecf20Sopenharmony_ci .mode = 0644, 4438c2ecf20Sopenharmony_ci .proc_handler = proc_doulongvec_ms_jiffies_minmax, 4448c2ecf20Sopenharmony_ci .extra1 = (void*) &parport_min_timeslice_value, 4458c2ecf20Sopenharmony_ci .extra2 = (void*) &parport_max_timeslice_value 4468c2ecf20Sopenharmony_ci }, 4478c2ecf20Sopenharmony_ci { 4488c2ecf20Sopenharmony_ci .procname = "spintime", 4498c2ecf20Sopenharmony_ci .data = &parport_default_spintime, 4508c2ecf20Sopenharmony_ci .maxlen = sizeof(parport_default_spintime), 4518c2ecf20Sopenharmony_ci .mode = 0644, 4528c2ecf20Sopenharmony_ci .proc_handler = proc_dointvec_minmax, 4538c2ecf20Sopenharmony_ci .extra1 = (void*) &parport_min_spintime_value, 4548c2ecf20Sopenharmony_ci .extra2 = (void*) &parport_max_spintime_value 4558c2ecf20Sopenharmony_ci }, 4568c2ecf20Sopenharmony_ci {} 4578c2ecf20Sopenharmony_ci }, 4588c2ecf20Sopenharmony_ci { 4598c2ecf20Sopenharmony_ci { 4608c2ecf20Sopenharmony_ci .procname = "default", 4618c2ecf20Sopenharmony_ci .mode = 0555, 4628c2ecf20Sopenharmony_ci .child = parport_default_sysctl_table.vars 4638c2ecf20Sopenharmony_ci }, 4648c2ecf20Sopenharmony_ci {} 4658c2ecf20Sopenharmony_ci }, 4668c2ecf20Sopenharmony_ci { 4678c2ecf20Sopenharmony_ci PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), 4688c2ecf20Sopenharmony_ci {} 4698c2ecf20Sopenharmony_ci }, 4708c2ecf20Sopenharmony_ci { 4718c2ecf20Sopenharmony_ci PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), 4728c2ecf20Sopenharmony_ci {} 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci}; 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ciint parport_proc_register(struct parport *port) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci struct parport_sysctl_table *t; 4808c2ecf20Sopenharmony_ci int i; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL); 4838c2ecf20Sopenharmony_ci if (t == NULL) 4848c2ecf20Sopenharmony_ci return -ENOMEM; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci t->device_dir[0].extra1 = port; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) 4898c2ecf20Sopenharmony_ci t->vars[i].extra1 = port; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci t->vars[0].data = &port->spintime; 4928c2ecf20Sopenharmony_ci t->vars[5].child = t->device_dir; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) 4958c2ecf20Sopenharmony_ci t->vars[6 + i].extra2 = &port->probe_info[i]; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci t->port_dir[0].procname = port->name; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci t->port_dir[0].child = t->vars; 5008c2ecf20Sopenharmony_ci t->parport_dir[0].child = t->port_dir; 5018c2ecf20Sopenharmony_ci t->dev_dir[0].child = t->parport_dir; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci t->sysctl_header = register_sysctl_table(t->dev_dir); 5048c2ecf20Sopenharmony_ci if (t->sysctl_header == NULL) { 5058c2ecf20Sopenharmony_ci kfree(t); 5068c2ecf20Sopenharmony_ci t = NULL; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci port->sysctl_table = t; 5098c2ecf20Sopenharmony_ci return 0; 5108c2ecf20Sopenharmony_ci} 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ciint parport_proc_unregister(struct parport *port) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci if (port->sysctl_table) { 5158c2ecf20Sopenharmony_ci struct parport_sysctl_table *t = port->sysctl_table; 5168c2ecf20Sopenharmony_ci port->sysctl_table = NULL; 5178c2ecf20Sopenharmony_ci unregister_sysctl_table(t->sysctl_header); 5188c2ecf20Sopenharmony_ci kfree(t); 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci return 0; 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ciint parport_device_proc_register(struct pardevice *device) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci struct parport_device_sysctl_table *t; 5268c2ecf20Sopenharmony_ci struct parport * port = device->port; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL); 5298c2ecf20Sopenharmony_ci if (t == NULL) 5308c2ecf20Sopenharmony_ci return -ENOMEM; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci t->dev_dir[0].child = t->parport_dir; 5338c2ecf20Sopenharmony_ci t->parport_dir[0].child = t->port_dir; 5348c2ecf20Sopenharmony_ci t->port_dir[0].procname = port->name; 5358c2ecf20Sopenharmony_ci t->port_dir[0].child = t->devices_root_dir; 5368c2ecf20Sopenharmony_ci t->devices_root_dir[0].child = t->device_dir; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci t->device_dir[0].procname = device->name; 5398c2ecf20Sopenharmony_ci t->device_dir[0].child = t->vars; 5408c2ecf20Sopenharmony_ci t->vars[0].data = &device->timeslice; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci t->sysctl_header = register_sysctl_table(t->dev_dir); 5438c2ecf20Sopenharmony_ci if (t->sysctl_header == NULL) { 5448c2ecf20Sopenharmony_ci kfree(t); 5458c2ecf20Sopenharmony_ci t = NULL; 5468c2ecf20Sopenharmony_ci } 5478c2ecf20Sopenharmony_ci device->sysctl_table = t; 5488c2ecf20Sopenharmony_ci return 0; 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ciint parport_device_proc_unregister(struct pardevice *device) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci if (device->sysctl_table) { 5548c2ecf20Sopenharmony_ci struct parport_device_sysctl_table *t = device->sysctl_table; 5558c2ecf20Sopenharmony_ci device->sysctl_table = NULL; 5568c2ecf20Sopenharmony_ci unregister_sysctl_table(t->sysctl_header); 5578c2ecf20Sopenharmony_ci kfree(t); 5588c2ecf20Sopenharmony_ci } 5598c2ecf20Sopenharmony_ci return 0; 5608c2ecf20Sopenharmony_ci} 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_cistatic int __init parport_default_proc_register(void) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci int ret; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci parport_default_sysctl_table.sysctl_header = 5678c2ecf20Sopenharmony_ci register_sysctl_table(parport_default_sysctl_table.dev_dir); 5688c2ecf20Sopenharmony_ci if (!parport_default_sysctl_table.sysctl_header) 5698c2ecf20Sopenharmony_ci return -ENOMEM; 5708c2ecf20Sopenharmony_ci ret = parport_bus_init(); 5718c2ecf20Sopenharmony_ci if (ret) { 5728c2ecf20Sopenharmony_ci unregister_sysctl_table(parport_default_sysctl_table. 5738c2ecf20Sopenharmony_ci sysctl_header); 5748c2ecf20Sopenharmony_ci return ret; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci return 0; 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_cistatic void __exit parport_default_proc_unregister(void) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci if (parport_default_sysctl_table.sysctl_header) { 5828c2ecf20Sopenharmony_ci unregister_sysctl_table(parport_default_sysctl_table. 5838c2ecf20Sopenharmony_ci sysctl_header); 5848c2ecf20Sopenharmony_ci parport_default_sysctl_table.sysctl_header = NULL; 5858c2ecf20Sopenharmony_ci } 5868c2ecf20Sopenharmony_ci parport_bus_exit(); 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci#else /* no sysctl or no procfs*/ 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ciint parport_proc_register(struct parport *pp) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci return 0; 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ciint parport_proc_unregister(struct parport *pp) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci return 0; 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ciint parport_device_proc_register(struct pardevice *device) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci return 0; 6048c2ecf20Sopenharmony_ci} 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ciint parport_device_proc_unregister(struct pardevice *device) 6078c2ecf20Sopenharmony_ci{ 6088c2ecf20Sopenharmony_ci return 0; 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic int __init parport_default_proc_register (void) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci return parport_bus_init(); 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cistatic void __exit parport_default_proc_unregister (void) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci parport_bus_exit(); 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci#endif 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_cisubsys_initcall(parport_default_proc_register) 6238c2ecf20Sopenharmony_cimodule_exit(parport_default_proc_unregister) 624