866881ec0cf81ed603705f8c01cebab3147def2f
[linux-2.6.git] / arch / mips / lasat / sysctl.c
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/uaccess.h>
33
34 #include <asm/time.h>
35
36 #ifdef CONFIG_DS1603
37 #include "ds1603.h"
38 #endif
39
40 /* Strategy function to write EEPROM after changing string entry */
41 int 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         r = sysctl_string(table, name,
48                           nlen, oldval, oldlenp, newval, newlen);
49         if (r < 0)
50                 return r;
51
52         if (newval && newlen)
53                 lasat_write_eeprom_info();
54
55         return 0;
56 }
57
58
59 /* And the same for proc */
60 int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
61                        void *buffer, size_t *lenp, loff_t *ppos)
62 {
63         int r;
64
65         r = proc_dostring(table, write, filp, buffer, lenp, ppos);
66         if ((!write) || r)
67                 return r;
68
69         lasat_write_eeprom_info();
70
71         return 0;
72 }
73
74 /* proc function to write EEPROM after changing int entry */
75 int proc_dolasatint(ctl_table *table, int write, struct file *filp,
76                        void *buffer, size_t *lenp, loff_t *ppos)
77 {
78         int r;
79
80         r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
81         if ((!write) || r)
82                 return r;
83
84         lasat_write_eeprom_info();
85
86         return 0;
87 }
88
89 #ifdef CONFIG_DS1603
90 static int rtctmp;
91
92 /* proc function to read/write RealTime Clock */
93 int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
94                        void *buffer, size_t *lenp, loff_t *ppos)
95 {
96         int r;
97
98         if (!write) {
99                 rtctmp = read_persistent_clock();
100                 /* check for time < 0 and set to 0 */
101                 if (rtctmp < 0)
102                         rtctmp = 0;
103         }
104         r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
105         if (r)
106                 return r;
107
108         if (write)
109                 rtc_mips_set_mmss(rtctmp);
110
111         return 0;
112 }
113 #endif
114
115 /* Sysctl for setting the IP addresses */
116 int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
117                     void *oldval, size_t *oldlenp,
118                     void *newval, size_t newlen)
119 {
120         int r;
121
122         r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
123         if (r < 0)
124                 return r;
125
126         if (newval && newlen)
127                 lasat_write_eeprom_info();
128
129         return 0;
130 }
131
132 #ifdef CONFIG_DS1603
133 /* Same for RTC */
134 int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
135                     void *oldval, size_t *oldlenp,
136                     void *newval, size_t newlen)
137 {
138         int r;
139
140         rtctmp = read_persistent_clock();
141         if (rtctmp < 0)
142                 rtctmp = 0;
143         r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
144         if (r < 0)
145                 return r;
146         if (newval && newlen)
147                 rtc_mips_set_mmss(rtctmp);
148
149         return r;
150 }
151 #endif
152
153 #ifdef CONFIG_INET
154 int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
155                        void *buffer, size_t *lenp, loff_t *ppos)
156 {
157         unsigned int ip;
158         char *p, c;
159         int len;
160         char ipbuf[32];
161
162         if (!table->data || !table->maxlen || !*lenp ||
163             (*ppos && !write)) {
164                 *lenp = 0;
165                 return 0;
166         }
167
168         if (write) {
169                 len = 0;
170                 p = buffer;
171                 while (len < *lenp) {
172                         if (get_user(c, p++))
173                                 return -EFAULT;
174                         if (c == 0 || c == '\n')
175                                 break;
176                         len++;
177                 }
178                 if (len >= sizeof(ipbuf)-1)
179                         len = sizeof(ipbuf) - 1;
180                 if (copy_from_user(ipbuf, buffer, len))
181                         return -EFAULT;
182                 ipbuf[len] = 0;
183                 *ppos += *lenp;
184                 /* Now see if we can convert it to a valid IP */
185                 ip = in_aton(ipbuf);
186                 *(unsigned int *)(table->data) = ip;
187                 lasat_write_eeprom_info();
188         } else {
189                 ip = *(unsigned int *)(table->data);
190                 sprintf(ipbuf, "%d.%d.%d.%d",
191                         (ip)       & 0xff,
192                         (ip >>  8) & 0xff,
193                         (ip >> 16) & 0xff,
194                         (ip >> 24) & 0xff);
195                 len = strlen(ipbuf);
196                 if (len > *lenp)
197                         len = *lenp;
198                 if (len)
199                         if (copy_to_user(buffer, ipbuf, len))
200                                 return -EFAULT;
201                 if (len < *lenp) {
202                         if (put_user('\n', ((char *) buffer) + len))
203                                 return -EFAULT;
204                         len++;
205                 }
206                 *lenp = len;
207                 *ppos += len;
208         }
209
210         return 0;
211 }
212 #endif
213
214 static int sysctl_lasat_prid(ctl_table *table, int *name, int nlen,
215                                      void *oldval, size_t *oldlenp,
216                                      void *newval, size_t newlen)
217 {
218         int r;
219
220         r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
221         if (r < 0)
222                 return r;
223         if (newval && newlen) {
224                 lasat_board_info.li_eeprom_info.prid = *(int *)newval;
225                 lasat_write_eeprom_info();
226                 lasat_init_board_info();
227         }
228         return 0;
229 }
230
231 int proc_lasat_prid(ctl_table *table, int write, struct file *filp,
232                        void *buffer, size_t *lenp, loff_t *ppos)
233 {
234         int r;
235
236         r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
237         if (r < 0)
238                 return r;
239         if (write) {
240                 lasat_board_info.li_eeprom_info.prid =
241                         lasat_board_info.li_prid;
242                 lasat_write_eeprom_info();
243                 lasat_init_board_info();
244         }
245         return 0;
246 }
247
248 extern int lasat_boot_to_service;
249
250 static ctl_table lasat_table[] = {
251         {
252                 .ctl_name       = CTL_UNNUMBERED,
253                 .procname       = "cpu-hz",
254                 .data           = &lasat_board_info.li_cpu_hz,
255                 .maxlen         = sizeof(int),
256                 .mode           = 0444,
257                 .proc_handler   = &proc_dointvec,
258                 .strategy       = &sysctl_intvec
259         },
260         {
261                 .ctl_name       = CTL_UNNUMBERED,
262                 .procname       = "bus-hz",
263                 .data           = &lasat_board_info.li_bus_hz,
264                 .maxlen         = sizeof(int),
265                 .mode           = 0444,
266                 .proc_handler   = &proc_dointvec,
267                 .strategy       = &sysctl_intvec
268         },
269         {
270                 .ctl_name       = CTL_UNNUMBERED,
271                 .procname       = "bmid",
272                 .data           = &lasat_board_info.li_bmid,
273                 .maxlen         = sizeof(int),
274                 .mode           = 0444,
275                 .proc_handler   = &proc_dointvec,
276                 .strategy       = &sysctl_intvec
277         },
278         {
279                 .ctl_name       = CTL_UNNUMBERED,
280                 .procname       = "prid",
281                 .data           = &lasat_board_info.li_prid,
282                 .maxlen         = sizeof(int),
283                 .mode           = 0644,
284                 .proc_handler   = &proc_lasat_prid,
285                 .strategy       = &sysctl_lasat_prid
286         },
287 #ifdef CONFIG_INET
288         {
289                 .ctl_name       = CTL_UNNUMBERED,
290                 .procname       = "ipaddr",
291                 .data           = &lasat_board_info.li_eeprom_info.ipaddr,
292                 .maxlen         = sizeof(int),
293                 .mode           = 0644,
294                 .proc_handler   = &proc_lasat_ip,
295                 .strategy       = &sysctl_lasat_intvec
296         },
297         {
298                 .ctl_name       = CTL_UNNUMBERED,
299                 .procname       = "netmask",
300                 .data           = &lasat_board_info.li_eeprom_info.netmask,
301                 .maxlen         = sizeof(int),
302                 .mode           = 0644,
303                 .proc_handler   = &proc_lasat_ip,
304                 .strategy       = &sysctl_lasat_intvec
305         },
306 #endif
307         {
308                 .ctl_name       = CTL_UNNUMBERED,
309                 .procname       = "passwd_hash",
310                 .data           = &lasat_board_info.li_eeprom_info.passwd_hash,
311                 .maxlen         =
312                         sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
313                 .mode           = 0600,
314                 .proc_handler   = &proc_dolasatstring,
315                 .strategy       = &sysctl_lasatstring
316         },
317         {
318                 .ctl_name       = CTL_UNNUMBERED,
319                 .procname       = "boot-service",
320                 .data           = &lasat_boot_to_service,
321                 .maxlen         = sizeof(int),
322                 .mode           = 0644,
323                 .proc_handler   = &proc_dointvec,
324                 .strategy       = &sysctl_intvec
325         },
326 #ifdef CONFIG_DS1603
327         {
328                 .ctl_name       = CTL_UNNUMBERED,
329                 .procname       = "rtc",
330                 .data           = &rtctmp,
331                 .maxlen         = sizeof(int),
332                 .mode           = 0644,
333                 .proc_handler   = &proc_dolasatrtc,
334                 .strategy       = &sysctl_lasat_rtc
335         },
336 #endif
337         {
338                 .ctl_name       = CTL_UNNUMBERED,
339                 .procname       = "namestr",
340                 .data           = &lasat_board_info.li_namestr,
341                 .maxlen         = sizeof(lasat_board_info.li_namestr),
342                 .mode           = 0444,
343                 .proc_handler   = &proc_dostring,
344                 .strategy       = &sysctl_string
345         },
346         {
347                 .ctl_name       = CTL_UNNUMBERED,
348                 .procname       = "typestr",
349                 .data           = &lasat_board_info.li_typestr,
350                 .maxlen         = sizeof(lasat_board_info.li_typestr),
351                 .mode           = 0444,
352                 .proc_handler   = &proc_dostring,
353                 .strategy       = &sysctl_string
354         },
355         {}
356 };
357
358 static ctl_table lasat_root_table[] = {
359         {
360                 .ctl_name       = CTL_UNNUMBERED,
361                 .procname       = "lasat",
362                 .mode           =  0555,
363                 .child          = lasat_table
364         },
365         {}
366 };
367
368 static int __init lasat_register_sysctl(void)
369 {
370         struct ctl_table_header *lasat_table_header;
371
372         lasat_table_header =
373                 register_sysctl_table(lasat_root_table);
374         if (!lasat_table_header) {
375                 printk(KERN_ERR "Unable to register LASAT sysctl\n");
376                 return -ENOMEM;
377         }
378
379         return 0;
380 }
381
382 __initcall(lasat_register_sysctl);