Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sbeproc.c
Go to the documentation of this file.
1 /* Copyright (C) 2004-2005 SBE, Inc.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  */
13 
14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15 
16 #include <linux/types.h>
17 #include <linux/module.h>
18 #include <linux/errno.h>
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sched.h>
23 #include <asm/uaccess.h>
24 #include "pmcc4_sysdep.h"
25 #include "sbecom_inline_linux.h"
26 #include "pmcc4_private.h"
27 #include "sbeproc.h"
28 
29 /* forwards */
30 void sbecom_get_brdinfo (ci_t *, struct sbe_brd_info *, u_int8_t *);
31 extern struct s_hdw_info hdw_info[MAX_BOARDS];
32 
33 #ifdef CONFIG_PROC_FS
34 
35 /********************************************************************/
36 /* procfs stuff */
37 /********************************************************************/
38 
39 
40 void
42 {
43  if (ci->dir_dev)
44  {
45  char dir[7 + SBE_IFACETMPL_SIZE + 1];
46  snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
47  remove_proc_entry("info", ci->dir_dev);
48  remove_proc_entry(dir, NULL);
49  ci->dir_dev = NULL;
50  }
51 }
52 
53 
54 static int
55 sbecom_proc_get_sbe_info (char *buffer, char **start, off_t offset,
56  int length, int *eof, void *priv)
57 {
58  ci_t *ci = (ci_t *) priv;
59  int len = 0;
60  char *spd;
61  struct sbe_brd_info *bip;
62 
63  if (!(bip = OS_kmalloc (sizeof (struct sbe_brd_info))))
64  {
65  return -ENOMEM;
66  }
67 #if 0
68 
69  pr_info(">> sbecom_proc_get_sbe_info: entered, offset %d. length %d.\n",
70  (int) offset, (int) length);
71 #endif
72 
73  {
74  hdw_info_t *hi = &hdw_info[ci->brdno];
75 
76  u_int8_t *bsn = 0;
77 
78  switch (hi->promfmt)
79  {
80  case PROM_FORMAT_TYPE1:
81  bsn = (u_int8_t *) hi->mfg_info.pft1.Serial;
82  break;
83  case PROM_FORMAT_TYPE2:
84  bsn = (u_int8_t *) hi->mfg_info.pft2.Serial;
85  break;
86  }
87 
88  sbecom_get_brdinfo (ci, bip, bsn);
89  }
90 
91 #if 0
92 
93  pr_info(">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n",
94  (char *) &bip->first_iname, (char *) &bip->first_iname,
95  (char *) &bip->last_iname, (char *) &bip->last_iname);
96 #endif
97  len += sprintf (buffer + len, "Board Type: ");
98  switch (bip->brd_id)
99  {
101  len += sprintf (buffer + len, "wanPMC-C1T3");
102  break;
104  len += sprintf (buffer + len, "wanPTMC-256T3 <E1>");
105  break;
107  len += sprintf (buffer + len, "wanPTMC-256T3 <T1>");
108  break;
110  len += sprintf (buffer + len, "wanPTMC-C24TE1");
111  break;
112 
115  len += sprintf (buffer + len, "wanPMC-C4T1E1");
116  break;
119  len += sprintf (buffer + len, "wanPMC-C2T1E1");
120  break;
123  len += sprintf (buffer + len, "wanPMC-C1T1E1");
124  break;
125 
127  len += sprintf (buffer + len, "wanPCI-C4T1E1");
128  break;
130  len += sprintf (buffer + len, "wanPCI-C2T1E1");
131  break;
133  len += sprintf (buffer + len, "wanPCI-C1T1E1");
134  break;
135 
136  default:
137  len += sprintf (buffer + len, "unknown");
138  break;
139  }
140  len += sprintf (buffer + len, " [%08X]\n", bip->brd_id);
141 
142  len += sprintf (buffer + len, "Board Number: %d\n", bip->brdno);
143  len += sprintf (buffer + len, "Hardware ID: 0x%02X\n", ci->hdw_bid);
144  len += sprintf (buffer + len, "Board SN: %06X\n", bip->brd_sn);
145  len += sprintf(buffer + len, "Board MAC: %pMF\n",
146  bip->brd_mac_addr);
147  len += sprintf (buffer + len, "Ports: %d\n", ci->max_port);
148  len += sprintf (buffer + len, "Channels: %d\n", bip->brd_chan_cnt);
149 #if 1
150  len += sprintf (buffer + len, "Interface: %s -> %s\n",
151  (char *) &bip->first_iname, (char *) &bip->last_iname);
152 #else
153  len += sprintf (buffer + len, "Interface: <not available> 1st %p lst %p\n",
154  (char *) &bip->first_iname, (char *) &bip->last_iname);
155 #endif
156 
157  switch (bip->brd_pci_speed)
158  {
159  case BINFO_PCI_SPEED_33:
160  spd = "33Mhz";
161  break;
162  case BINFO_PCI_SPEED_66:
163  spd = "66Mhz";
164  break;
165  default:
166  spd = "<not available>";
167  break;
168  }
169  len += sprintf (buffer + len, "PCI Bus Speed: %s\n", spd);
170  len += sprintf (buffer + len, "Release: %s\n", ci->release);
171 
172 #ifdef SBE_PMCC4_ENABLE
173  {
174  extern int cxt1e1_max_mru;
175 #if 0
176  extern int max_chans_used;
177  extern int cxt1e1_max_mtu;
178 #endif
179  extern int max_rxdesc_used, max_txdesc_used;
180 
181  len += sprintf (buffer + len, "\ncxt1e1_max_mru: %d\n", cxt1e1_max_mru);
182 #if 0
183  len += sprintf (buffer + len, "\nmax_chans_used: %d\n", max_chans_used);
184  len += sprintf (buffer + len, "cxt1e1_max_mtu: %d\n", cxt1e1_max_mtu);
185 #endif
186  len += sprintf (buffer + len, "max_rxdesc_used: %d\n", max_rxdesc_used);
187  len += sprintf (buffer + len, "max_txdesc_used: %d\n", max_txdesc_used);
188  }
189 #endif
190 
191  OS_kfree (bip); /* cleanup */
192 
193  /***
194  * How to be a proc read function
195  * ------------------------------
196  * Prototype:
197  * int f(char *buffer, char **start, off_t offset,
198  * int count, int *peof, void *dat)
199  *
200  * Assume that the buffer is "count" bytes in size.
201  *
202  * If you know you have supplied all the data you
203  * have, set *peof.
204  *
205  * You have three ways to return data:
206  * 0) Leave *start = NULL. (This is the default.)
207  * Put the data of the requested offset at that
208  * offset within the buffer. Return the number (n)
209  * of bytes there are from the beginning of the
210  * buffer up to the last byte of data. If the
211  * number of supplied bytes (= n - offset) is
212  * greater than zero and you didn't signal eof
213  * and the reader is prepared to take more data
214  * you will be called again with the requested
215  * offset advanced by the number of bytes
216  * absorbed. This interface is useful for files
217  * no larger than the buffer.
218  * 1) Set *start = an unsigned long value less than
219  * the buffer address but greater than zero.
220  * Put the data of the requested offset at the
221  * beginning of the buffer. Return the number of
222  * bytes of data placed there. If this number is
223  * greater than zero and you didn't signal eof
224  * and the reader is prepared to take more data
225  * you will be called again with the requested
226  * offset advanced by *start. This interface is
227  * useful when you have a large file consisting
228  * of a series of blocks which you want to count
229  * and return as wholes.
230  * (Hack by [email protected])
231  * 2) Set *start = an address within the buffer.
232  * Put the data of the requested offset at *start.
233  * Return the number of bytes of data placed there.
234  * If this number is greater than zero and you
235  * didn't signal eof and the reader is prepared to
236  * take more data you will be called again with the
237  * requested offset advanced by the number of bytes
238  * absorbed.
239  */
240 
241 #if 1
242  /* #4 - interpretation of above = set EOF, return len */
243  *eof = 1;
244 #endif
245 
246 #if 0
247  /*
248  * #1 - from net/wireless/atmel.c RLD NOTE -there's something wrong with
249  * this plagarized code which results in this routine being called TWICE.
250  * The second call returns ZERO, resulting in hidden failure, but at
251  * least only a single message set is being displayed.
252  */
253  if (len <= offset + length)
254  *eof = 1;
255  *start = buffer + offset;
256  len -= offset;
257  if (len > length)
258  len = length;
259  if (len < 0)
260  len = 0;
261 #endif
262 
263 #if 0 /* #2 from net/tokenring/olympic.c +
264  * lanstreamer.c */
265  {
266  off_t begin = 0;
267  int size = 0;
268  off_t pos = 0;
269 
270  size = len;
271  pos = begin + size;
272  if (pos < offset)
273  {
274  len = 0;
275  begin = pos;
276  }
277  *start = buffer + (offset - begin); /* Start of wanted data */
278  len -= (offset - begin); /* Start slop */
279  if (len > length)
280  len = length; /* Ending slop */
281  }
282 #endif
283 
284 #if 0 /* #3 from
285  * char/ftape/lowlevel/ftape-proc.c */
286  len = strlen (buffer);
287  *start = NULL;
288  if (offset + length >= len)
289  *eof = 1;
290  else
291  *eof = 0;
292 #endif
293 
294 #if 0
295  pr_info(">> proc_fs: returned len = %d., start %p\n", len, start); /* RLD DEBUG */
296 #endif
297 
298 /***
299  using NONE: returns = 314.314.314.
300  using #1 : returns = 314, 0.
301  using #2 : returns = 314, 0, 0.
302  using #3 : returns = 314, 314.
303  using #4 : returns = 314, 314.
304 ***/
305 
306  return len;
307 }
308 
309 /* initialize the /proc subsystem for the specific SBE driver */
310 
311 int __init
313 {
314  struct proc_dir_entry *e;
315  char dir[7 + SBE_IFACETMPL_SIZE + 1];
316 
317  /* create a directory in the root procfs */
318  snprintf(dir, sizeof(dir), "driver/%s", ci->devname);
319  ci->dir_dev = proc_mkdir(dir, NULL);
320  if (!ci->dir_dev)
321  {
322  pr_err("Unable to create directory /proc/driver/%s\n", ci->devname);
323  goto fail;
324  }
325  e = create_proc_read_entry ("info", S_IFREG | S_IRUGO,
326  ci->dir_dev, sbecom_proc_get_sbe_info, ci);
327  if (!e)
328  {
329  pr_err("Unable to create entry /proc/driver/%s/info\n", ci->devname);
330  goto fail;
331  }
332  return 0;
333 
334 fail:
336  return 1;
337 }
338 
339 #else /*** ! CONFIG_PROC_FS ***/
340 
341 /* stubbed off dummy routines */
342 
343 void
345 {
346 }
347 
348 int __init
350 {
351  return 0;
352 }
353 
354 #endif /*** CONFIG_PROC_FS ***/
355 
356 
357 /*** End-of-File ***/