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