staging: dgnc: removes proc code
[firefly-linux-kernel-4.4.55.git] / drivers / staging / dgnc / dgnc_mgmt.c
1 /*
2  * Copyright 2003 Digi International (www.digi.com)
3  *      Scott H Kilau <Scott_Kilau at digi dot com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
12  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13  * PURPOSE.  See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE! 
21  *
22  *      This is shared code between Digi's CVS archive and the
23  *      Linux Kernel sources.
24  *      Changing the source just for reformatting needlessly breaks
25  *      our CVS diff history.
26  *
27  *      Send any bug fixes/changes to:  Eng.Linux at digi dot com. 
28  *      Thank you. 
29  *
30  */
31
32 /************************************************************************
33  * 
34  * This file implements the mgmt functionality for the
35  * Neo and ClassicBoard based product lines.
36  * 
37  ************************************************************************
38  * $Id: dgnc_mgmt.c,v 1.2 2010/12/14 20:08:29 markh Exp $
39  */
40 #include <linux/kernel.h>
41 #include <linux/ctype.h>
42 #include <linux/sched.h>        /* For jiffies, task states */
43 #include <linux/interrupt.h>    /* For tasklet and interrupt structs/defines */
44 #include <linux/serial_reg.h>
45 #include <linux/termios.h>
46 #include <asm/uaccess.h>        /* For copy_from_user/copy_to_user */
47
48 #include "dgnc_driver.h"
49 #include "dgnc_pci.h"
50 #include "dgnc_kcompat.h"       /* Kernel 2.4/2.6 compat includes */
51 #include "dgnc_mgmt.h"
52 #include "dpacompat.h"
53
54
55 /* Our "in use" variables, to enforce 1 open only */
56 static int dgnc_mgmt_in_use[MAXMGMTDEVICES];
57
58
59 /*
60  * dgnc_mgmt_open()  
61  *
62  * Open the mgmt/downld/dpa device
63  */  
64 int dgnc_mgmt_open(struct inode *inode, struct file *file)
65 {
66         unsigned long lock_flags;
67         unsigned int minor = iminor(inode);
68
69         DPR_MGMT(("dgnc_mgmt_open start.\n"));
70
71         DGNC_LOCK(dgnc_global_lock, lock_flags); 
72
73         /* mgmt device */
74         if (minor < MAXMGMTDEVICES) {
75                 /* Only allow 1 open at a time on mgmt device */
76                 if (dgnc_mgmt_in_use[minor]) {
77                         DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
78                         return (-EBUSY);
79                 }
80                 dgnc_mgmt_in_use[minor]++;
81         }
82         else {
83                 DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
84                 return (-ENXIO);
85         }
86
87         DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
88
89         DPR_MGMT(("dgnc_mgmt_open finish.\n"));
90
91         return 0;
92 }
93
94
95 /*
96  * dgnc_mgmt_close()
97  *
98  * Open the mgmt/dpa device
99  */  
100 int dgnc_mgmt_close(struct inode *inode, struct file *file)
101 {
102         unsigned long lock_flags;
103         unsigned int minor = iminor(inode);
104
105         DPR_MGMT(("dgnc_mgmt_close start.\n"));
106
107         DGNC_LOCK(dgnc_global_lock, lock_flags); 
108
109         /* mgmt device */
110         if (minor < MAXMGMTDEVICES) {
111                 if (dgnc_mgmt_in_use[minor]) {
112                         dgnc_mgmt_in_use[minor] = 0;
113                 }
114         }
115         DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
116
117         DPR_MGMT(("dgnc_mgmt_close finish.\n"));
118
119         return 0;
120 }
121
122
123 /*
124  * dgnc_mgmt_ioctl()
125  *
126  * ioctl the mgmt/dpa device
127  */  
128 #ifdef HAVE_UNLOCKED_IOCTL
129 long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
130 {
131         struct inode *inode = file->f_dentry->d_inode;
132 #else        
133 int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
134 {
135 #endif
136         unsigned long lock_flags;
137         void __user *uarg = (void __user *) arg;
138
139         DPR_MGMT(("dgnc_mgmt_ioctl start.\n"));
140
141         switch (cmd) {
142
143         case DIGI_GETDD:
144         {
145                 /*
146                  * This returns the total number of boards
147                  * in the system, as well as driver version
148                  * and has space for a reserved entry
149                  */
150                 struct digi_dinfo ddi;
151
152                 DGNC_LOCK(dgnc_global_lock, lock_flags); 
153
154                 ddi.dinfo_nboards = dgnc_NumBoards;
155                 sprintf(ddi.dinfo_version, "%s", DG_PART);
156
157                 DGNC_UNLOCK(dgnc_global_lock, lock_flags); 
158
159                 DPR_MGMT(("DIGI_GETDD returning numboards: %d version: %s\n",
160                         ddi.dinfo_nboards, ddi.dinfo_version));
161
162                 if (copy_to_user(uarg, &ddi, sizeof (ddi)))
163                         return(-EFAULT);
164
165                 break;
166         }
167
168         case DIGI_GETBD:
169         {
170                 int brd;
171
172                 struct digi_info di;
173
174                 if (copy_from_user(&brd, uarg, sizeof(int))) {
175                         return(-EFAULT);
176                 }
177
178                 DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd));
179
180                 if ((brd < 0) || (brd > dgnc_NumBoards) || (dgnc_NumBoards == 0))
181                         return (-ENODEV);
182
183                 memset(&di, 0, sizeof(di));
184
185                 di.info_bdnum = brd;
186
187                 DGNC_LOCK(dgnc_Board[brd]->bd_lock, lock_flags); 
188
189                 di.info_bdtype = dgnc_Board[brd]->dpatype;
190                 di.info_bdstate = dgnc_Board[brd]->dpastatus;
191                 di.info_ioport = 0;
192                 di.info_physaddr = (ulong) dgnc_Board[brd]->membase;
193                 di.info_physsize = (ulong) dgnc_Board[brd]->membase - dgnc_Board[brd]->membase_end;
194                 if (dgnc_Board[brd]->state != BOARD_FAILED)
195                         di.info_nports = dgnc_Board[brd]->nasync;
196                 else
197                         di.info_nports = 0;
198
199                 DGNC_UNLOCK(dgnc_Board[brd]->bd_lock, lock_flags); 
200
201                 DPR_MGMT(("DIGI_GETBD returning type: %x state: %x ports: %x size: %x\n",
202                         di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize));
203
204                 if (copy_to_user(uarg, &di, sizeof (di)))
205                         return (-EFAULT);
206
207                 break;
208         }
209
210         case DIGI_GET_NI_INFO:
211         {
212                 struct channel_t *ch;
213                 struct ni_info ni;
214                 uchar mstat = 0;
215                 uint board = 0;
216                 uint channel = 0;
217
218                 if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) {
219                         return(-EFAULT);
220                 }
221
222                 DPR_MGMT(("DIGI_GETBD asking about board: %d channel: %d\n",
223                         ni.board, ni.channel));
224
225                 board = ni.board;
226                 channel = ni.channel;
227
228                 /* Verify boundaries on board */
229                 if ((board < 0) || (board > dgnc_NumBoards) || (dgnc_NumBoards == 0))
230                         return (-ENODEV);
231
232                 /* Verify boundaries on channel */
233                 if ((channel < 0) || (channel > dgnc_Board[board]->nasync))
234                         return (-ENODEV);
235
236                 ch = dgnc_Board[board]->channels[channel];
237
238                 if (!ch || ch->magic != DGNC_CHANNEL_MAGIC)
239                         return (-ENODEV);
240
241                 memset(&ni, 0, sizeof(ni));
242                 ni.board = board;
243                 ni.channel = channel;
244
245                 DGNC_LOCK(ch->ch_lock, lock_flags);
246
247                 mstat = (ch->ch_mostat | ch->ch_mistat);
248
249                 if (mstat & UART_MCR_DTR) {
250                         ni.mstat |= TIOCM_DTR;
251                         ni.dtr = TIOCM_DTR;
252                 }
253                 if (mstat & UART_MCR_RTS) {
254                         ni.mstat |= TIOCM_RTS;
255                         ni.rts = TIOCM_RTS;
256                 }
257                 if (mstat & UART_MSR_CTS) {
258                         ni.mstat |= TIOCM_CTS;
259                         ni.cts = TIOCM_CTS;
260                 }
261                 if (mstat & UART_MSR_RI) {
262                         ni.mstat |= TIOCM_RI;
263                         ni.ri = TIOCM_RI;
264                 }
265                 if (mstat & UART_MSR_DCD) {
266                         ni.mstat |= TIOCM_CD;
267                         ni.dcd = TIOCM_CD;
268                 }
269                 if (mstat & UART_MSR_DSR)
270                         ni.mstat |= TIOCM_DSR;
271
272                 ni.iflag = ch->ch_c_iflag;
273                 ni.oflag = ch->ch_c_oflag;
274                 ni.cflag = ch->ch_c_cflag;
275                 ni.lflag = ch->ch_c_lflag;
276
277                 if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS)
278                         ni.hflow = 1;
279                 else
280                         ni.hflow = 0;
281
282                 if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI))
283                         ni.recv_stopped = 1;
284                 else
285                         ni.recv_stopped = 0;
286
287                 if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP))
288                         ni.xmit_stopped = 1;
289                 else
290                         ni.xmit_stopped = 0;
291
292                 ni.curtx = ch->ch_txcount;
293                 ni.currx = ch->ch_rxcount;
294
295                 ni.baud = ch->ch_old_baud;
296
297                 DGNC_UNLOCK(ch->ch_lock, lock_flags);
298
299                 if (copy_to_user(uarg, &ni, sizeof(ni)))
300                         return (-EFAULT);
301
302                 break;
303         }
304
305
306         }
307
308         DPR_MGMT(("dgnc_mgmt_ioctl finish.\n"));
309
310         return 0;
311 }