import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / isdn / eicon / linchr.c
1 /*
2  * Copyright (C) Eicon Technology Corporation, 2000.
3  *
4  * Eicon File Revision :    1.12  
5  *
6  * This software may be used and distributed according to the terms
7  * of the GNU General Public License, incorporated herein by reference.
8  *
9  */
10
11 #define __NO_VERSION__
12 #include <linux/module.h>
13
14 #include <linux/kernel.h>
15 #include <linux/poll.h>
16 #include <linux/fs.h>
17 #include <linux/slab.h>
18
19 #undef N_DATA
20
21 #include "adapter.h"
22 #include "divas.h"
23 #include "divalog.h"
24
25 extern int DivasCardNext;
26 void UxPause(long ms);
27 int DivasGetMem(mem_block_t *);
28
29 #define DIA_IOCTL_UNLOCK 12
30 void UnlockDivas(void);
31
32 int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile, 
33                          unsigned int command, unsigned long arg)
34 {
35         byte *pUserCards, card_i;
36         word wCardNum;
37
38         switch (command)
39         {
40                 case DIA_IOCTL_CONFIG:
41                 {
42                         dia_config_t DivaConfig;
43                         if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t)))
44                                 return -EFAULT;
45                         DivasCardConfig(&DivaConfig);
46                         return 0;
47                 }
48
49                 case DIA_IOCTL_DETECT:
50                         pUserCards = (byte *) arg;
51
52                         if (!verify_area(VERIFY_WRITE, pUserCards, 20))
53                         {
54                                 if(__put_user(DivasCardNext, pUserCards++))
55                                         return -EFAULT;
56
57                                 for (card_i=1; card_i < 20; card_i++)
58                                 {
59                                         if(__put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++))
60                                                 return -EFAULT;
61                                 }
62                         }
63                         else return -EFAULT;
64
65                         return 0;
66
67                 case DIA_IOCTL_START:
68                 {
69                         dia_start_t DivaStart;
70                         if (copy_from_user(&DivaStart, (void *)arg, sizeof(dia_start_t)))
71                                 return -EFAULT;
72                         return DivasCardStart(DivaStart.card_id);
73                 }
74
75                 case DIA_IOCTL_FLAVOUR:
76                         return 0;
77
78                 case DIA_IOCTL_LOAD:
79                 {
80                         dia_load_t DivaLoad;
81                         if(copy_from_user(&DivaLoad, (void *)arg, sizeof(dia_load_t)))
82                                 return -EFAULT;
83                         if (!verify_area(VERIFY_READ, DivaLoad.code,DivaLoad.length))
84                         {
85                                 if (DivasCardLoad(&DivaLoad))
86                                 {
87                                         printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n");
88                                         return -EINVAL;
89                                 }
90                                 return 0;
91                         }
92                         return -EFAULT;
93                 }
94                 case DIA_IOCTL_LOG:
95                 {
96                         dia_log_t DivaLog;
97                         if (copy_from_user(&DivaLog, (void *) arg, sizeof(dia_log_t)))
98                                 return -EFAULT;
99                         DivasLog(&DivaLog);
100                         return 0;
101                 }
102
103                 case DIA_IOCTL_XLOG_REQ:
104                         if(get_user(wCardNum, (word *) arg))
105                                 return -EFAULT;
106                         DivasXlogReq(wCardNum);
107                         return 0;
108
109                 case DIA_IOCTL_GET_NUM:
110                         if(put_user(DivasCardNext, (int *)arg))
111                                 return -EFAULT;
112                         return 0;
113
114                 case DIA_IOCTL_GET_LIST:
115                 {
116                         dia_card_list_t cards;
117                         DPRINTF(("divas: DIA_IOCTL_GET_LIST"));
118                         DivasGetList(&cards);
119                         if(copy_to_user((void *)arg, &cards, sizeof(cards)))
120                                 return -EFAULT;
121                         return 0;
122                 }
123                 case DIA_IOCTL_GET_MEM:
124                 {
125                         mem_block_t mem_block;
126                         if (copy_from_user(&mem_block, (void *)arg, sizeof(mem_block_t)))
127                                 return -EFAULT;
128                         DivasGetMem(&mem_block);
129                         return 0;
130                 }
131
132                 case DIA_IOCTL_UNLOCK:
133                         UnlockDivas();
134                         return 0;
135
136                 default:
137                         return -EINVAL;
138         }
139         return -EINVAL;
140 }
141
142 unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
143 {
144         word wMask = 0;
145
146         if (!DivasLogFifoEmpty())
147                 wMask |= POLLIN | POLLRDNORM;
148         return wMask;
149 }
150
151 ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset)
152 {
153         klog_t *pClientLogBuffer = (klog_t *) pUserBuffer;
154         klog_t *pHeadItem;
155
156         if (BufferSize < sizeof(klog_t))
157                 return -EIO;
158
159         pHeadItem = (klog_t *) DivasLogFifoRead();
160
161         if (pHeadItem)
162         {
163                 if(copy_to_user(pClientLogBuffer, pHeadItem, sizeof(klog_t)))
164                 {
165                         kfree(pHeadItem);
166                         return -EFAULT;
167                 }
168                 kfree(pHeadItem);
169                 return sizeof(klog_t);
170         }
171
172         return 0;
173 }
174 static int private_usage_count;
175
176 int do_open(struct inode *pInode, struct file *pFile)
177 {
178         MOD_INC_USE_COUNT;
179 #ifdef MODULE
180         private_usage_count++;
181 #endif
182         return 0;
183 }
184
185 int do_release(struct inode *pInode, struct file *pFile)
186 {
187         MOD_DEC_USE_COUNT;
188 #ifdef MODULE
189         private_usage_count--;
190 #endif
191         return 0;
192 }
193
194 void UnlockDivas(void)
195 {
196         while (private_usage_count > 0)
197         {
198                 private_usage_count--;
199                 MOD_DEC_USE_COUNT;
200         }
201 }