at v5.2 268 lines 5.4 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Thomas Horsten <thh@lasat.com> 4 * Copyright (C) 2000 LASAT Networks A/S. 5 * 6 * Routines specific to the LASAT boards 7 */ 8#include <linux/types.h> 9#include <asm/lasat/lasat.h> 10 11#include <linux/sysctl.h> 12#include <linux/stddef.h> 13#include <linux/init.h> 14#include <linux/fs.h> 15#include <linux/ctype.h> 16#include <linux/string.h> 17#include <linux/net.h> 18#include <linux/inet.h> 19#include <linux/uaccess.h> 20 21#include <asm/time.h> 22 23#ifdef CONFIG_DS1603 24#include "ds1603.h" 25#endif 26 27 28/* And the same for proc */ 29int proc_dolasatstring(struct ctl_table *table, int write, 30 void *buffer, size_t *lenp, loff_t *ppos) 31{ 32 int r; 33 34 r = proc_dostring(table, write, buffer, lenp, ppos); 35 if ((!write) || r) 36 return r; 37 38 lasat_write_eeprom_info(); 39 40 return 0; 41} 42 43#ifdef CONFIG_DS1603 44static int rtctmp; 45 46/* proc function to read/write RealTime Clock */ 47int proc_dolasatrtc(struct ctl_table *table, int write, 48 void *buffer, size_t *lenp, loff_t *ppos) 49{ 50 struct timespec64 ts; 51 int r; 52 53 if (!write) { 54 read_persistent_clock64(&ts); 55 rtctmp = ts.tv_sec; 56 /* check for time < 0 and set to 0 */ 57 if (rtctmp < 0) 58 rtctmp = 0; 59 } 60 r = proc_dointvec(table, write, buffer, lenp, ppos); 61 if (r) 62 return r; 63 64 if (write) { 65 /* 66 * Due to the RTC hardware limitation, we can not actually 67 * use the full 64-bit range here. 68 */ 69 ts.tv_sec = rtctmp; 70 ts.tv_nsec = 0; 71 72 update_persistent_clock64(ts); 73 } 74 75 return 0; 76} 77#endif 78 79#ifdef CONFIG_INET 80int proc_lasat_ip(struct ctl_table *table, int write, 81 void *buffer, size_t *lenp, loff_t *ppos) 82{ 83 unsigned int ip; 84 char *p, c; 85 int len; 86 char ipbuf[32]; 87 88 if (!table->data || !table->maxlen || !*lenp || 89 (*ppos && !write)) { 90 *lenp = 0; 91 return 0; 92 } 93 94 if (write) { 95 len = 0; 96 p = buffer; 97 while (len < *lenp) { 98 if (get_user(c, p++)) 99 return -EFAULT; 100 if (c == 0 || c == '\n') 101 break; 102 len++; 103 } 104 if (len >= sizeof(ipbuf)-1) 105 len = sizeof(ipbuf) - 1; 106 if (copy_from_user(ipbuf, buffer, len)) 107 return -EFAULT; 108 ipbuf[len] = 0; 109 *ppos += *lenp; 110 /* Now see if we can convert it to a valid IP */ 111 ip = in_aton(ipbuf); 112 *(unsigned int *)(table->data) = ip; 113 lasat_write_eeprom_info(); 114 } else { 115 ip = *(unsigned int *)(table->data); 116 sprintf(ipbuf, "%d.%d.%d.%d", 117 (ip) & 0xff, 118 (ip >> 8) & 0xff, 119 (ip >> 16) & 0xff, 120 (ip >> 24) & 0xff); 121 len = strlen(ipbuf); 122 if (len > *lenp) 123 len = *lenp; 124 if (len) 125 if (copy_to_user(buffer, ipbuf, len)) 126 return -EFAULT; 127 if (len < *lenp) { 128 if (put_user('\n', ((char *) buffer) + len)) 129 return -EFAULT; 130 len++; 131 } 132 *lenp = len; 133 *ppos += len; 134 } 135 136 return 0; 137} 138#endif 139 140int proc_lasat_prid(struct ctl_table *table, int write, 141 void *buffer, size_t *lenp, loff_t *ppos) 142{ 143 int r; 144 145 r = proc_dointvec(table, write, buffer, lenp, ppos); 146 if (r < 0) 147 return r; 148 if (write) { 149 lasat_board_info.li_eeprom_info.prid = 150 lasat_board_info.li_prid; 151 lasat_write_eeprom_info(); 152 lasat_init_board_info(); 153 } 154 return 0; 155} 156 157extern int lasat_boot_to_service; 158 159static struct ctl_table lasat_table[] = { 160 { 161 .procname = "cpu-hz", 162 .data = &lasat_board_info.li_cpu_hz, 163 .maxlen = sizeof(int), 164 .mode = 0444, 165 .proc_handler = proc_dointvec, 166 }, 167 { 168 .procname = "bus-hz", 169 .data = &lasat_board_info.li_bus_hz, 170 .maxlen = sizeof(int), 171 .mode = 0444, 172 .proc_handler = proc_dointvec, 173 }, 174 { 175 .procname = "bmid", 176 .data = &lasat_board_info.li_bmid, 177 .maxlen = sizeof(int), 178 .mode = 0444, 179 .proc_handler = proc_dointvec, 180 }, 181 { 182 .procname = "prid", 183 .data = &lasat_board_info.li_prid, 184 .maxlen = sizeof(int), 185 .mode = 0644, 186 .proc_handler = proc_lasat_prid, 187 }, 188#ifdef CONFIG_INET 189 { 190 .procname = "ipaddr", 191 .data = &lasat_board_info.li_eeprom_info.ipaddr, 192 .maxlen = sizeof(int), 193 .mode = 0644, 194 .proc_handler = proc_lasat_ip, 195 }, 196 { 197 .procname = "netmask", 198 .data = &lasat_board_info.li_eeprom_info.netmask, 199 .maxlen = sizeof(int), 200 .mode = 0644, 201 .proc_handler = proc_lasat_ip, 202 }, 203#endif 204 { 205 .procname = "passwd_hash", 206 .data = &lasat_board_info.li_eeprom_info.passwd_hash, 207 .maxlen = 208 sizeof(lasat_board_info.li_eeprom_info.passwd_hash), 209 .mode = 0600, 210 .proc_handler = proc_dolasatstring, 211 }, 212 { 213 .procname = "boot-service", 214 .data = &lasat_boot_to_service, 215 .maxlen = sizeof(int), 216 .mode = 0644, 217 .proc_handler = proc_dointvec, 218 }, 219#ifdef CONFIG_DS1603 220 { 221 .procname = "rtc", 222 .data = &rtctmp, 223 .maxlen = sizeof(int), 224 .mode = 0644, 225 .proc_handler = proc_dolasatrtc, 226 }, 227#endif 228 { 229 .procname = "namestr", 230 .data = &lasat_board_info.li_namestr, 231 .maxlen = sizeof(lasat_board_info.li_namestr), 232 .mode = 0444, 233 .proc_handler = proc_dostring, 234 }, 235 { 236 .procname = "typestr", 237 .data = &lasat_board_info.li_typestr, 238 .maxlen = sizeof(lasat_board_info.li_typestr), 239 .mode = 0444, 240 .proc_handler = proc_dostring, 241 }, 242 {} 243}; 244 245static struct ctl_table lasat_root_table[] = { 246 { 247 .procname = "lasat", 248 .mode = 0555, 249 .child = lasat_table 250 }, 251 {} 252}; 253 254static int __init lasat_register_sysctl(void) 255{ 256 struct ctl_table_header *lasat_table_header; 257 258 lasat_table_header = 259 register_sysctl_table(lasat_root_table); 260 if (!lasat_table_header) { 261 printk(KERN_ERR "Unable to register LASAT sysctl\n"); 262 return -ENOMEM; 263 } 264 265 return 0; 266} 267 268arch_initcall(lasat_register_sysctl);