blob: 4575a829766d64b5497b4c29a0b324b4c92e9055 [file] [log] [blame]
Brian Murphy1f21d2b2007-08-21 22:34:16 +02001/*
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 <linux/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
47 mutex_lock(&lasat_info_mutex);
48 r = sysctl_string(table, name,
49 nlen, oldval, oldlenp, newval, newlen);
50 if (r < 0) {
51 mutex_unlock(&lasat_info_mutex);
52 return r;
53 }
54 if (newval && newlen)
55 lasat_write_eeprom_info();
56 mutex_unlock(&lasat_info_mutex);
57
58 return 1;
59}
60
61
62/* And the same for proc */
63int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
64 void *buffer, size_t *lenp, loff_t *ppos)
65{
66 int r;
67
68 mutex_lock(&lasat_info_mutex);
69 r = proc_dostring(table, write, filp, buffer, lenp, ppos);
70 if ((!write) || r) {
71 mutex_unlock(&lasat_info_mutex);
72 return r;
73 }
74 lasat_write_eeprom_info();
75 mutex_unlock(&lasat_info_mutex);
76
77 return 0;
78}
79
80/* proc function to write EEPROM after changing int entry */
81int proc_dolasatint(ctl_table *table, int write, struct file *filp,
82 void *buffer, size_t *lenp, loff_t *ppos)
83{
84 int r;
85
86 mutex_lock(&lasat_info_mutex);
87 r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
88 if ((!write) || r) {
89 mutex_unlock(&lasat_info_mutex);
90 return r;
91 }
92 lasat_write_eeprom_info();
93 mutex_unlock(&lasat_info_mutex);
94
95 return 0;
96}
97
98static int rtctmp;
99
100#ifdef CONFIG_DS1603
101/* proc function to read/write RealTime Clock */
102int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
103 void *buffer, size_t *lenp, loff_t *ppos)
104{
105 int r;
106
107 mutex_lock(&lasat_info_mutex);
108 if (!write) {
109 rtctmp = ds1603_read();
110 /* check for time < 0 and set to 0 */
111 if (rtctmp < 0)
112 rtctmp = 0;
113 }
114 r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
115 if ((!write) || r) {
116 mutex_unlock(&lasat_info_mutex);
117 return r;
118 }
119 ds1603_set(rtctmp);
120 mutex_unlock(&lasat_info_mutex);
121
122 return 0;
123}
124#endif
125
126/* Sysctl for setting the IP addresses */
127int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
128 void *oldval, size_t *oldlenp,
129 void *newval, size_t newlen)
130{
131 int r;
132
133 mutex_lock(&lasat_info_mutex);
134 r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
135 if (r < 0) {
136 mutex_unlock(&lasat_info_mutex);
137 return r;
138 }
139 if (newval && newlen)
140 lasat_write_eeprom_info();
141 mutex_unlock(&lasat_info_mutex);
142
143 return 1;
144}
145
146#ifdef CONFIG_DS1603
147/* Same for RTC */
148int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
149 void *oldval, size_t *oldlenp,
150 void *newval, size_t newlen)
151{
152 int r;
153
154 mutex_lock(&lasat_info_mutex);
155 rtctmp = ds1603_read();
156 if (rtctmp < 0)
157 rtctmp = 0;
158 r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
159 if (r < 0) {
160 mutex_unlock(&lasat_info_mutex);
161 return r;
162 }
163 if (newval && newlen)
164 ds1603_set(rtctmp);
165 mutex_unlock(&lasat_info_mutex);
166
167 return 1;
168}
169#endif
170
171#ifdef CONFIG_INET
172static char lasat_bcastaddr[16];
173
174void update_bcastaddr(void)
175{
176 unsigned int ip;
177
178 ip = (lasat_board_info.li_eeprom_info.ipaddr &
179 lasat_board_info.li_eeprom_info.netmask) |
180 ~lasat_board_info.li_eeprom_info.netmask;
181
182 sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
183 (ip) & 0xff,
184 (ip >> 8) & 0xff,
185 (ip >> 16) & 0xff,
186 (ip >> 24) & 0xff);
187}
188
189static char proc_lasat_ipbuf[32];
190
191/* Parsing of IP address */
192int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
193 void *buffer, size_t *lenp, loff_t *ppos)
194{
195 unsigned int ip;
196 char *p, c;
197 int len;
198
199 if (!table->data || !table->maxlen || !*lenp ||
200 (*ppos && !write)) {
201 *lenp = 0;
202 return 0;
203 }
204
205 mutex_lock(&lasat_info_mutex);
206 if (write) {
207 len = 0;
208 p = buffer;
209 while (len < *lenp) {
210 if (get_user(c, p++)) {
211 mutex_unlock(&lasat_info_mutex);
212 return -EFAULT;
213 }
214 if (c == 0 || c == '\n')
215 break;
216 len++;
217 }
218 if (len >= sizeof(proc_lasat_ipbuf)-1)
219 len = sizeof(proc_lasat_ipbuf) - 1;
220 if (copy_from_user(proc_lasat_ipbuf, buffer, len)) {
221 mutex_unlock(&lasat_info_mutex);
222 return -EFAULT;
223 }
224 proc_lasat_ipbuf[len] = 0;
225 *ppos += *lenp;
226 /* Now see if we can convert it to a valid IP */
227 ip = in_aton(proc_lasat_ipbuf);
228 *(unsigned int *)(table->data) = ip;
229 lasat_write_eeprom_info();
230 } else {
231 ip = *(unsigned int *)(table->data);
232 sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d",
233 (ip) & 0xff,
234 (ip >> 8) & 0xff,
235 (ip >> 16) & 0xff,
236 (ip >> 24) & 0xff);
237 len = strlen(proc_lasat_ipbuf);
238 if (len > *lenp)
239 len = *lenp;
240 if (len)
241 if (copy_to_user(buffer, proc_lasat_ipbuf, len)) {
242 mutex_unlock(&lasat_info_mutex);
243 return -EFAULT;
244 }
245 if (len < *lenp) {
246 if (put_user('\n', ((char *) buffer) + len)) {
247 mutex_unlock(&lasat_info_mutex);
248 return -EFAULT;
249 }
250 len++;
251 }
252 *lenp = len;
253 *ppos += len;
254 }
255 update_bcastaddr();
256 mutex_unlock(&lasat_info_mutex);
257
258 return 0;
259}
260#endif /* defined(CONFIG_INET) */
261
262static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
263 void *oldval, size_t *oldlenp,
264 void *newval, size_t newlen)
265{
266 int r;
267
268 mutex_lock(&lasat_info_mutex);
269 r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
270 if (r < 0) {
271 mutex_unlock(&lasat_info_mutex);
272 return r;
273 }
274
275 if (newval && newlen) {
276 if (name && *name == LASAT_PRID)
277 lasat_board_info.li_eeprom_info.prid = *(int *)newval;
278
279 lasat_write_eeprom_info();
280 lasat_init_board_info();
281 }
282 mutex_unlock(&lasat_info_mutex);
283
284 return 0;
285}
286
287int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
288 void *buffer, size_t *lenp, loff_t *ppos)
289{
290 int r;
291
292 mutex_lock(&lasat_info_mutex);
293 r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
294 if ((!write) || r) {
295 mutex_unlock(&lasat_info_mutex);
296 return r;
297 }
298 if (filp && filp->f_path.dentry) {
299 if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
300 lasat_board_info.li_eeprom_info.prid =
301 lasat_board_info.li_prid;
302 if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
303 lasat_board_info.li_eeprom_info.debugaccess =
304 lasat_board_info.li_debugaccess;
305 }
306 lasat_write_eeprom_info();
307 mutex_unlock(&lasat_info_mutex);
308
309 return 0;
310}
311
312extern int lasat_boot_to_service;
313
314#ifdef CONFIG_SYSCTL
315
316static ctl_table lasat_table[] = {
317 {
318 .ctl_name = CTL_UNNUMBERED,
319 .procname = "cpu-hz",
320 .data = &lasat_board_info.li_cpu_hz,
321 .maxlen = sizeof(int),
322 .mode = 0444,
323 .proc_handler = &proc_dointvec,
324 .strategy = &sysctl_intvec
325 },
326 {
327 .ctl_name = CTL_UNNUMBERED,
328 .procname = "bus-hz",
329 .data = &lasat_board_info.li_bus_hz,
330 .maxlen = sizeof(int),
331 .mode = 0444,
332 .proc_handler = &proc_dointvec,
333 .strategy = &sysctl_intvec
334 },
335 {
336 .ctl_name = CTL_UNNUMBERED,
337 .procname = "bmid",
338 .data = &lasat_board_info.li_bmid,
339 .maxlen = sizeof(int),
340 .mode = 0444,
341 .proc_handler = &proc_dointvec,
342 .strategy = &sysctl_intvec
343 },
344 {
345 .ctl_name = CTL_UNNUMBERED,
346 .procname = "prid",
347 .data = &lasat_board_info.li_prid,
348 .maxlen = sizeof(int),
349 .mode = 0644,
350 .proc_handler = &proc_lasat_eeprom_value,
351 .strategy = &sysctl_lasat_eeprom_value
352 },
353#ifdef CONFIG_INET
354 {
355 .ctl_name = CTL_UNNUMBERED,
356 .procname = "ipaddr",
357 .data = &lasat_board_info.li_eeprom_info.ipaddr,
358 .maxlen = sizeof(int),
359 .mode = 0644,
360 .proc_handler = &proc_lasat_ip,
361 .strategy = &sysctl_lasat_intvec
362 },
363 {
364 .ctl_name = LASAT_NETMASK,
365 .procname = "netmask",
366 .data = &lasat_board_info.li_eeprom_info.netmask,
367 .maxlen = sizeof(int),
368 .mode = 0644,
369 .proc_handler = &proc_lasat_ip,
370 .strategy = &sysctl_lasat_intvec
371 },
372 {
373 .ctl_name = CTL_UNNUMBERED,
374 .procname = "bcastaddr",
375 .data = &lasat_bcastaddr,
376 .maxlen = sizeof(lasat_bcastaddr),
377 .mode = 0600,
378 .proc_handler = &proc_dostring,
379 .strategy = &sysctl_string
380 },
381#endif
382 {
383 .ctl_name = CTL_UNNUMBERED,
384 .procname = "passwd_hash",
385 .data = &lasat_board_info.li_eeprom_info.passwd_hash,
386 .maxlen =
387 sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
388 .mode = 0600,
389 .proc_handler = &proc_dolasatstring,
390 .strategy = &sysctl_lasatstring
391 },
392 {
393 .ctl_name = CTL_UNNUMBERED,
394 .procname = "boot-service",
395 .data = &lasat_boot_to_service,
396 .maxlen = sizeof(int),
397 .mode = 0644,
398 .proc_handler = &proc_dointvec,
399 .strategy = &sysctl_intvec
400 },
401#ifdef CONFIG_DS1603
402 {
403 .ctl_name = CTL_UNNUMBERED,
404 .procname = "rtc",
405 .data = &rtctmp,
406 .maxlen = sizeof(int),
407 .mode = 0644,
408 .proc_handler = &proc_dolasatrtc,
409 .strategy = &sysctl_lasat_rtc
410 },
411#endif
412 {
413 .ctl_name = CTL_UNNUMBERED,
414 .procname = "namestr",
415 .data = &lasat_board_info.li_namestr,
416 .maxlen = sizeof(lasat_board_info.li_namestr),
417 .mode = 0444,
418 .proc_handler = &proc_dostring,
419 .strategy = &sysctl_string
420 },
421 {
422 .ctl_name = CTL_UNNUMBERED,
423 .procname = "typestr",
424 .data = &lasat_board_info.li_typestr,
425 .maxlen = sizeof(lasat_board_info.li_typestr),
426 .mode = 0444,
427 .proc_handler = &proc_dostring,
428 .strategy = &sysctl_string
429 },
430 {}
431};
432
433static ctl_table lasat_root_table[] = {
434 {
435 .ctl_name = CTL_UNNUMBERED,
436 .procname = "lasat",
437 .mode = 0555,
438 .child = lasat_table
439 },
440 {}
441};
442
443static int __init lasat_register_sysctl(void)
444{
445 struct ctl_table_header *lasat_table_header;
446
447 lasat_table_header =
448 register_sysctl_table(lasat_root_table);
449
450 return 0;
451}
452
453__initcall(lasat_register_sysctl);
454#endif /* CONFIG_SYSCTL */