94e426e4d98b0177b72065bf630c4eae1b490925
[pandora-kernel.git] / drivers / staging / ft1000 / ft1000-pcmcia / ft1000_proc.c
1 /*---------------------------------------------------------------------------
2    FT1000 driver for Flarion Flash OFDM NIC Device
3
4    Copyright (C) 2006 Patrik Ostrihon, All rights reserved.
5    Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved.
6
7    This program is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2 of the License, or (at your option) any
10    later version. This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13    more details. You should have received a copy of the GNU General Public
14    License along with this program; if not, write to the
15    Free Software Foundation, Inc., 59 Temple Place -
16    Suite 330, Boston, MA 02111-1307, USA.
17 -----------------------------------------------------------------------------*/
18
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/proc_fs.h>
22 #include <linux/seq_file.h>
23 #include <linux/string.h>
24 #include <linux/vmalloc.h>
25 #include <linux/netdevice.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include "ft1000.h"
29
30 #define FT1000_PROC "ft1000"
31 #define MAX_FILE_LEN 255
32
33 #define seq_putx(m, message, size, var) \
34         seq_printf(m, message); \
35         for(i = 0; i < (size - 1); i++) { \
36                 seq_printf(m, "%02x:", var[i]); \
37         } \
38         seq_printf(m, "%02x\n", var[i])
39
40 #define seq_putd(m, message, size, var) \
41         seq_printf(m, message); \
42         for(i = 0; i < (size - 1); i++) { \
43                 seq_printf(m, "%d.", var[i]); \
44         } \
45         seq_printf(m, "%d\n", var[i])
46
47 static int ft1000ReadProc(struct seq_file *m, void *v)
48 {
49         static const char *status[] = {
50                 "Idle (Disconnect)", "Searching", "Active (Connected)",
51                 "Waiting for L2", "Sleep", "No Coverage", "", ""
52         };
53         static const char *signal[] = { "", "*", "**", "***", "****" };
54
55         struct net_device *dev = m->private;
56         struct ft1000_info *info = netdev_priv(dev);
57         int i;
58         int strength;
59         int quality;
60         struct timeval tv;
61         time_t delta;
62
63         if (info->AsicID == ELECTRABUZZ_ID) {
64                 if (info->ProgConStat != 0xFF) {
65                         info->LedStat =
66                                 ft1000_read_dpram(dev, FT1000_DSP_LED);
67                         info->ConStat =
68                                 ft1000_read_dpram(dev, FT1000_DSP_CON_STATE);
69                 } else {
70                         info->ConStat = 0xf;
71                 }
72         } else {
73                 if (info->ProgConStat != 0xFF) {
74                         info->LedStat =
75                                 ntohs(ft1000_read_dpram_mag_16(
76                                               dev, FT1000_MAG_DSP_LED,
77                                               FT1000_MAG_DSP_LED_INDX));
78                         info->ConStat =
79                                 ntohs(ft1000_read_dpram_mag_16(
80                                               dev, FT1000_MAG_DSP_CON_STATE,
81                                               FT1000_MAG_DSP_CON_STATE_INDX));
82                 } else {
83                         info->ConStat = 0xf;
84                 }
85         }
86
87         i = (info->LedStat) & 0xf;
88         switch (i) {
89         case 0x1:
90                 strength = 1;
91                 break;
92         case 0x3:
93                 strength = 2;
94                 break;
95         case 0x7:
96                 strength = 3;
97                 break;
98         case 0xf:
99                 strength = 4;
100                 break;
101         default:
102                 strength = 0;
103         }
104
105         i = (info->LedStat >> 8) & 0xf;
106         switch (i) {
107         case 0x1:
108                 quality = 1;
109                 break;
110         case 0x3:
111                 quality = 2;
112                 break;
113         case 0x7:
114                 quality = 3;
115                 break;
116         case 0xf:
117                 quality = 4;
118                 break;
119         default:
120                 quality = 0;
121         }
122
123         do_gettimeofday(&tv);
124         delta = tv.tv_sec - info->ConTm;
125         seq_printf(m, "Connection Time: %02ld:%02ld:%02ld\n",
126                          ((delta / 3600) % 24), ((delta / 60) % 60), (delta % 60));
127         seq_printf(m, "Connection Time[s]: %ld\n", delta);
128         seq_printf(m, "Asic ID: %s\n",
129                          info->AsicID ==
130                          ELECTRABUZZ_ID ? "ELECTRABUZZ ASIC" : "MAGNEMITE ASIC");
131         seq_putx(m, "SKU: ", SKUSZ, info->Sku);
132         seq_putx(m, "EUI64: ", EUISZ, info->eui64);
133         seq_putd(m, "DSP version number: ", DSPVERSZ, info->DspVer);
134         seq_putx(m, "Hardware Serial Number: ", HWSERNUMSZ, info->HwSerNum);
135         seq_putx(m, "Caliberation Version: ", CALVERSZ, info->RfCalVer);
136         seq_putd(m, "Caliberation Date: ", CALDATESZ, info->RfCalDate);
137         seq_printf(m, "Media State: %s\n",
138                          (info->mediastate) ? "link" : "no link");
139         seq_printf(m, "Connection Status: %s\n", status[info->ConStat & 0x7]);
140         seq_printf(m, "RX packets: %ld\n", info->stats.rx_packets);
141         seq_printf(m, "TX packets: %ld\n", info->stats.tx_packets);
142         seq_printf(m, "RX bytes: %ld\n", info->stats.rx_bytes);
143         seq_printf(m, "TX bytes: %ld\n", info->stats.tx_bytes);
144         seq_printf(m, "Signal Strength: %s\n", signal[strength]);
145         seq_printf(m, "Signal Quality: %s\n", signal[quality]);
146         return 0;
147 }
148
149 /*
150  * seq_file wrappers for procfile show routines.
151  */
152 static int ft1000_proc_open(struct inode *inode, struct file *file)
153 {
154         return single_open(file, ft1000ReadProc, PDE_DATA(inode));
155 }
156
157 static const struct file_operations ft1000_proc_fops = {
158         .open           = ft1000_proc_open,
159         .read           = seq_read,
160         .llseek         = seq_lseek,
161         .release        = single_release,
162 };
163
164 static int ft1000NotifyProc(struct notifier_block *this, unsigned long event,
165                                 void *ptr)
166 {
167         struct net_device *dev = ptr;
168         struct ft1000_info *info;
169
170         info = netdev_priv(dev);
171
172         switch (event) {
173         case NETDEV_CHANGENAME:
174                 remove_proc_entry(info->netdevname, info->ft1000_proc_dir);
175                 proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
176                                  &ft1000_proc_fops, dev);
177                 snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
178                 break;
179         }
180         return NOTIFY_DONE;
181 }
182
183 static struct notifier_block ft1000_netdev_notifier = {
184         .notifier_call = ft1000NotifyProc
185 };
186
187 void ft1000InitProc(struct net_device *dev)
188 {
189         struct ft1000_info *info;
190
191         info = netdev_priv(dev);
192
193         info->ft1000_proc_dir = proc_mkdir(FT1000_PROC, init_net.proc_net);
194
195         proc_create_data(dev->name, 0644, info->ft1000_proc_dir,
196                          &ft1000_proc_fops, dev);
197
198         snprintf(info->netdevname, IFNAMSIZ, "%s", dev->name);
199         register_netdevice_notifier(&ft1000_netdev_notifier);
200 }
201
202 void ft1000CleanupProc(struct net_device *dev)
203 {
204         struct ft1000_info *info;
205
206         info = netdev_priv(dev);
207
208         remove_proc_entry(dev->name, info->ft1000_proc_dir);
209         remove_proc_entry(FT1000_PROC, init_net.proc_net);
210         unregister_netdevice_notifier(&ft1000_netdev_notifier);
211 }