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
do_ioctl(struct inode * pDivasInode,struct file * pDivasFile,unsigned int command,unsigned long arg)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
do_poll(struct file * pFile,struct poll_table_struct * pPollTable)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
do_read(struct file * pFile,char * pUserBuffer,size_t BufferSize,loff_t * pOffset)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
do_open(struct inode * pInode,struct file * pFile)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
do_release(struct inode * pInode,struct file * pFile)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
UnlockDivas(void)194 void UnlockDivas(void)
195 {
196 while (private_usage_count > 0)
197 {
198 private_usage_count--;
199 MOD_DEC_USE_COUNT;
200 }
201 }
202