1/* 2 * Thomas Horsten <thh@lasat.com> 3 * Copyright (C) 2000 LASAT Networks A/S. 4 * 5 * This program is free software; you can distribute it and/or modify it 6 * under the terms of the GNU General Public License (Version 2) as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 17 * 18 * Routines specific to the LASAT boards 19 */ 20#include <linux/types.h> 21#include <asm/lasat/lasat.h> 22 23#include <linux/module.h> 24#include <linux/sysctl.h> 25#include <linux/stddef.h> 26#include <linux/init.h> 27#include <linux/fs.h> 28#include <linux/ctype.h> 29#include <linux/string.h> 30#include <linux/net.h> 31#include <linux/inet.h> 32#include <linux/mutex.h> 33#include <asm/uaccess.h> 34 35#include "sysctl.h" 36#include "ds1603.h" 37 38static DEFINE_MUTEX(lasat_info_mutex); 39 40/* Strategy function to write EEPROM after changing string entry */ 41int sysctl_lasatstring(ctl_table *table, int *name, int nlen, 42 void *oldval, size_t *oldlenp, 43 void *newval, size_t newlen) 44{ 45 int r; 46 mutex_lock(&lasat_info_mutex); 47 r = sysctl_string(table, name, 48 nlen, oldval, oldlenp, newval, newlen); 49 if (r < 0) { 50 mutex_unlock(&lasat_info_mutex); 51 return r; 52 } 53 if (newval && newlen) { 54 lasat_write_eeprom_info(); 55 } 56 mutex_unlock(&lasat_info_mutex); 57 return 1; 58} 59 60 61/* And the same for proc */ 62int proc_dolasatstring(ctl_table *table, int write, struct file *filp, 63 void *buffer, size_t *lenp, loff_t *ppos) 64{ 65 int r; 66 mutex_lock(&lasat_info_mutex); 67 r = proc_dostring(table, write, filp, buffer, lenp, ppos); 68 if ( (!write) || r) { 69 mutex_unlock(&lasat_info_mutex); 70 return r; 71 } 72 lasat_write_eeprom_info(); 73 mutex_unlock(&lasat_info_mutex); 74 return 0; 75} 76 77/* proc function to write EEPROM after changing int entry */ 78int proc_dolasatint(ctl_table *table, int write, struct file *filp, 79 void *buffer, size_t *lenp, loff_t *ppos) 80{ 81 int r; 82 mutex_lock(&lasat_info_mutex); 83 r = proc_dointvec(table, write, filp, buffer, lenp, ppos); 84 if ( (!write) || r) { 85 mutex_unlock(&lasat_info_mutex); 86 return r; 87 } 88 lasat_write_eeprom_info(); 89 mutex_unlock(&lasat_info_mutex); 90 return 0; 91} 92 93static int rtctmp; 94 95#ifdef CONFIG_DS1603 96/* proc function to read/write RealTime Clock */ 97int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, 98 void *buffer, size_t *lenp, loff_t *ppos) 99{ 100 int r; 101 mutex_lock(&lasat_info_mutex); 102 if (!write) { 103 rtctmp = ds1603_read(); 104 /* check for time < 0 and set to 0 */ 105 if (rtctmp < 0) 106 rtctmp = 0; 107 } 108 r = proc_dointvec(table, write, filp, buffer, lenp, ppos); 109 if ( (!write) || r) { 110 mutex_unlock(&lasat_info_mutex); 111 return r; 112 } 113 ds1603_set(rtctmp); 114 mutex_unlock(&lasat_info_mutex); 115 return 0; 116} 117#endif 118 119/* Sysctl for setting the IP addresses */ 120int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen, 121 void *oldval, size_t *oldlenp, 122 void *newval, size_t newlen) 123{ 124 int r; 125 mutex_lock(&lasat_info_mutex); 126 r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); 127 if (r < 0) { 128 mutex_unlock(&lasat_info_mutex); 129 return r; 130 } 131 if (newval && newlen) { 132 lasat_write_eeprom_info(); 133 } 134 mutex_unlock(&lasat_info_mutex); 135 return 1; 136} 137 138#ifdef CONFIG_DS1603 139/* Same for RTC */ 140int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen, 141 void *oldval, size_t *oldlenp, 142 void *newval, size_t newlen) 143{ 144 int r; 145 mutex_lock(&lasat_info_mutex); 146 rtctmp = ds1603_read(); 147 if (rtctmp < 0) 148 rtctmp = 0; 149 r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); 150 if (r < 0) { 151 mutex_unlock(&lasat_info_mutex); 152 return r; 153 } 154 if (newval && newlen) { 155 ds1603_set(rtctmp); 156 } 157 mutex_unlock(&lasat_info_mutex); 158 return 1; 159} 160#endif 161 162#ifdef CONFIG_INET 163static char lasat_bcastaddr[16]; 164 165void update_bcastaddr(void) 166{ 167 unsigned int ip; 168 169 ip = (lasat_board_info.li_eeprom_info.ipaddr & 170 lasat_board_info.li_eeprom_info.netmask) | 171 ~lasat_board_info.li_eeprom_info.netmask; 172 173 sprintf(lasat_bcastaddr, "%d.%d.%d.%d", 174 (ip ) & 0xff, 175 (ip >> 8) & 0xff, 176 (ip >> 16) & 0xff, 177 (ip >> 24) & 0xff); 178} 179 180static char proc_lasat_ipbuf[32]; 181/* Parsing of IP address */ 182int proc_lasat_ip(ctl_table *table, int write, struct file *filp, 183 void *buffer, size_t *lenp, loff_t *ppos) 184{ 185 int len; 186 unsigned int ip; 187 char *p, c; 188 189 if (!table->data || !table->maxlen || !*lenp || 190 (*ppos && !write)) { 191 *lenp = 0; 192 return 0; 193 } 194 195 mutex_lock(&lasat_info_mutex); 196 if (write) { 197 len = 0; 198 p = buffer; 199 while (len < *lenp) { 200 if(get_user(c, p++)) { 201 mutex_unlock(&lasat_info_mutex); 202 return -EFAULT; 203 } 204 if (c == 0 || c == '\n') 205 break; 206 len++; 207 } 208 if (len >= sizeof(proc_lasat_ipbuf)-1) 209 len = sizeof(proc_lasat_ipbuf) - 1; 210 if (copy_from_user(proc_lasat_ipbuf, buffer, len)) 211 { 212 mutex_unlock(&lasat_info_mutex); 213 return -EFAULT; 214 } 215 proc_lasat_ipbuf[len] = 0; 216 *ppos += *lenp; 217 /* Now see if we can convert it to a valid IP */ 218 ip = in_aton(proc_lasat_ipbuf); 219 *(unsigned int *)(table->data) = ip; 220 lasat_write_eeprom_info(); 221 } else { 222 ip = *(unsigned int *)(table->data); 223 sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d", 224 (ip ) & 0xff, 225 (ip >> 8) & 0xff, 226 (ip >> 16) & 0xff, 227 (ip >> 24) & 0xff); 228 len = strlen(proc_lasat_ipbuf); 229 if (len > *lenp) 230 len = *lenp; 231 if (len) 232 if(copy_to_user(buffer, proc_lasat_ipbuf, len)) { 233 mutex_unlock(&lasat_info_mutex); 234 return -EFAULT; 235 } 236 if (len < *lenp) { 237 if(put_user('\n', ((char *) buffer) + len)) { 238 mutex_unlock(&lasat_info_mutex); 239 return -EFAULT; 240 } 241 len++; 242 } 243 *lenp = len; 244 *ppos += len; 245 } 246 update_bcastaddr(); 247 mutex_unlock(&lasat_info_mutex); 248 return 0; 249} 250#endif /* defined(CONFIG_INET) */ 251 252static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, 253 void *oldval, size_t *oldlenp, 254 void *newval, size_t newlen) 255{ 256 int r; 257 258 mutex_lock(&lasat_info_mutex); 259 r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen); 260 if (r < 0) { 261 mutex_unlock(&lasat_info_mutex); 262 return r; 263 } 264 265 if (newval && newlen) 266 { 267 if (name && *name == LASAT_PRID) 268 lasat_board_info.li_eeprom_info.prid = *(int*)newval; 269 270 lasat_write_eeprom_info(); 271 lasat_init_board_info(); 272 } 273 mutex_unlock(&lasat_info_mutex); 274 275 return 0; 276} 277 278int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, 279 void *buffer, size_t *lenp, loff_t *ppos) 280{ 281 int r; 282 mutex_lock(&lasat_info_mutex); 283 r = proc_dointvec(table, write, filp, buffer, lenp, ppos); 284 if ( (!write) || r) { 285 mutex_unlock(&lasat_info_mutex); 286 return r; 287 } 288 if (filp && filp->f_path.dentry) 289 { 290 if (!strcmp(filp->f_path.dentry->d_name.name, "prid")) 291 lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid; 292 if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess")) 293 lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess; 294 } 295 lasat_write_eeprom_info(); 296 mutex_unlock(&lasat_info_mutex); 297 return 0; 298} 299 300extern int lasat_boot_to_service; 301 302#ifdef CONFIG_SYSCTL 303 304static ctl_table lasat_table[] = { 305 { 306 .ctl_name = CTL_UNNUMBERED, 307 .procname = "cpu-hz", 308 .data = &lasat_board_info.li_cpu_hz, 309 .maxlen = sizeof(int), 310 .mode = 0444, 311 .proc_handler = &proc_dointvec, 312 .strategy = &sysctl_intvec 313 }, 314 { 315 .ctl_name = CTL_UNNUMBERED, 316 .procname = "bus-hz", 317 .data = &lasat_board_info.li_bus_hz, 318 .maxlen = sizeof(int), 319 .mode = 0444, 320 .proc_handler = &proc_dointvec, 321 .strategy = &sysctl_intvec 322 }, 323 { 324 .ctl_name = CTL_UNNUMBERED, 325 .procname = "bmid", 326 .data = &lasat_board_info.li_bmid, 327 .maxlen = sizeof(int), 328 .mode = 0444, 329 .proc_handler = &proc_dointvec, 330 .strategy = &sysctl_intvec 331 }, 332 { 333 .ctl_name = CTL_UNNUMBERED, 334 .procname = "prid", 335 .data = &lasat_board_info.li_prid, 336 .maxlen = sizeof(int), 337 .mode = 0644, 338 .proc_handler = &proc_lasat_eeprom_value, 339 .strategy = &sysctl_lasat_eeprom_value 340 }, 341#ifdef CONFIG_INET 342 { 343 .ctl_name = CTL_UNNUMBERED, 344 .procname = "ipaddr", 345 .data = &lasat_board_info.li_eeprom_info.ipaddr, 346 .maxlen = sizeof(int), 347 .mode = 0644, 348 .proc_handler = &proc_lasat_ip, 349 .strategy = &sysctl_lasat_intvec 350 }, 351 { 352 .ctl_name = LASAT_NETMASK, 353 .procname = "netmask", 354 .data = &lasat_board_info.li_eeprom_info.netmask, 355 .maxlen = sizeof(int), 356 .mode = 0644, 357 .proc_handler = &proc_lasat_ip, 358 .strategy = &sysctl_lasat_intvec 359 }, 360 { 361 .ctl_name = CTL_UNNUMBERED, 362 .procname = "bcastaddr", 363 .data = &lasat_bcastaddr, 364 .maxlen = sizeof(lasat_bcastaddr), 365 .mode = 0600, 366 .proc_handler = &proc_dostring, 367 .strategy = &sysctl_string 368 }, 369#endif 370 { 371 .ctl_name = CTL_UNNUMBERED, 372 .procname = "passwd_hash", 373 .data = &lasat_board_info.li_eeprom_info.passwd_hash, 374 .maxlen = sizeof(lasat_board_info.li_eeprom_info.passwd_hash), 375 .mode = 0600, 376 .proc_handler = &proc_dolasatstring, 377 .strategy = &sysctl_lasatstring 378 }, 379 { 380 .ctl_name = CTL_UNNUMBERED, 381 .procname = "boot-service", 382 .data = &lasat_boot_to_service, 383 .maxlen = sizeof(int), 384 .mode = 0644, 385 .proc_handler = &proc_dointvec, 386 .strategy = &sysctl_intvec 387 }, 388#ifdef CONFIG_DS1603 389 { 390 .ctl_name = CTL_UNNUMBERED, 391 .procname = "rtc", 392 .data = &rtctmp, 393 .maxlen = sizeof(int), 394 .mode = 0644, 395 .proc_handler = &proc_dolasatrtc, 396 .strategy = &sysctl_lasat_rtc 397 }, 398#endif 399 { 400 .ctl_name = CTL_UNNUMBERED, 401 .procname = "namestr", 402 .data = &lasat_board_info.li_namestr, 403 .maxlen = sizeof(lasat_board_info.li_namestr), 404 .mode = 0444, 405 .proc_handler = &proc_dostring, 406 .strategy = &sysctl_string 407 }, 408 { 409 .ctl_name = CTL_UNNUMBERED, 410 .procname = "typestr", 411 .data = &lasat_board_info.li_typestr, 412 .maxlen = sizeof(lasat_board_info.li_typestr), 413 .mode = 0444, 414 .proc_handler = &proc_dostring, 415 .strategy = &sysctl_string 416 }, 417 {} 418}; 419 420static ctl_table lasat_root_table[] = { 421 { 422 .ctl_name = CTL_UNNUMBERED, 423 .procname = "lasat", 424 .mode = 0555, 425 .child = lasat_table 426 }, 427 {} 428}; 429 430static int __init lasat_register_sysctl(void) 431{ 432 struct ctl_table_header *lasat_table_header; 433 434 lasat_table_header = 435 register_sysctl_table(lasat_root_table); 436 437 return 0; 438} 439 440__initcall(lasat_register_sysctl); 441#endif /* CONFIG_SYSCTL */ 442