|
1 /* me8100.c */ |
|
2 /* Device driver for Meilhaus me8100 board. |
|
3 * ======================================== |
|
4 * |
|
5 * Copyright (C) 2001 Meilhaus Electronic GmbH (support@meilhaus.de) |
|
6 * |
|
7 * This file is free software; you can redistribute it and/or modify |
|
8 * it under the terms of the GNU General Public License as published by |
|
9 * the Free Software Foundation; either version 2 of the License, or |
|
10 * (at your option) any later version. |
|
11 * |
|
12 * This program is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 * GNU General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License |
|
18 * along with this program; if not, write to the Free Software |
|
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
20 */ |
|
21 |
|
22 |
|
23 |
|
24 /* |
|
25 * Source File : me8100.c |
|
26 * Destination : me8100.o |
|
27 * Author : GG (Guenter Gebhardt) |
|
28 * |
|
29 * File History: Version Date Editor Action |
|
30 *--------------------------------------------------------------------- |
|
31 * 1.00.00 01.01.10 GG first release |
|
32 * |
|
33 * 1.00.01 01.02.14 GG Add new ioctls: |
|
34 * get_board_info |
|
35 * get_int count |
|
36 * |
|
37 * 1.01.00 01.10.08 GG Port to Kernel 2.4 |
|
38 *--------------------------------------------------------------------- |
|
39 * |
|
40 * Description: |
|
41 * |
|
42 * Contains the entire driver-module code for the |
|
43 * Meilhaus ME-8100 board. However, the definitions and type |
|
44 * declarations are kept in the headerfile called me8100.h. |
|
45 * |
|
46 */ |
|
47 |
|
48 |
|
49 /* |
|
50 * User application could also include the kernel header files. But the |
|
51 * real kernel functions are protected by #ifdef __KERNEL__. |
|
52 */ |
|
53 #ifndef __KERNEL__ |
|
54 # define __KERNEL__ |
|
55 #endif |
|
56 |
|
57 |
|
58 /* |
|
59 * This must be defined before module.h is included. Not needed, when |
|
60 * it is a built in driver. |
|
61 */ |
|
62 #define MODULE |
|
63 |
|
64 |
|
65 /* |
|
66 * If we are compiling for a multiprocessor system, |
|
67 * we have to define this. |
|
68 */ |
|
69 #include <linux/config.h> |
|
70 #ifdef CONFIG_SMP |
|
71 # define __SMP__ |
|
72 #endif |
|
73 |
|
74 |
|
75 /* |
|
76 * Basic facilities for modules. |
|
77 * Defines __module_kernel_version. |
|
78 * Includes <linux/version.h> (UTS_RELEASE, LINUX_VERSION_CODE, ...) |
|
79 */ |
|
80 #include <linux/module.h> |
|
81 |
|
82 /* |
|
83 * Needed for the registration of I/O and MEMORY regions. |
|
84 * (request_region, ...) |
|
85 */ |
|
86 #include <linux/ioport.h> |
|
87 |
|
88 #include <linux/fs.h> |
|
89 #include <linux/sched.h> |
|
90 #include <linux/interrupt.h> |
|
91 #include <linux/pci.h> |
|
92 #include <linux/malloc.h> |
|
93 #include <asm/io.h> |
|
94 #include <asm/system.h> |
|
95 #include <asm/uaccess.h> |
|
96 #include <linux/errno.h> |
|
97 #include <linux/delay.h> |
|
98 #include <linux/fs.h> |
|
99 #include <linux/mm.h> |
|
100 #include <linux/unistd.h> |
|
101 |
|
102 |
|
103 #include <linux/poll.h> |
|
104 #include <linux/vmalloc.h> |
|
105 #include <asm/pgtable.h> |
|
106 #include <asm/uaccess.h> |
|
107 |
|
108 |
|
109 /* Compatibility file for kernels from 2.0 up to 2.4 */ |
|
110 #include "sysdep.h" |
|
111 |
|
112 |
|
113 /* Include-File for the Meilhaus ME-8100 I/O board */ |
|
114 #include "me8100.h" |
|
115 |
|
116 |
|
117 /* Board specific data are kept global */ |
|
118 static me8100_info_type info_vec[SORT_COUNT * ME8100_MAX_DEVICES]; |
|
119 |
|
120 |
|
121 /* Number of boards, detected from the BIOS */ |
|
122 static int me8100_board_count; |
|
123 |
|
124 |
|
125 /* Major Device Number. 0 means to get it automatically from the System */ |
|
126 static unsigned int major = 0; |
|
127 |
|
128 |
|
129 /* Prototypes */ |
|
130 static int me8100_open(struct inode *, struct file *); |
|
131 static int me8100_release(struct inode *, struct file *); |
|
132 static int me8100_ioctl(struct inode *, struct file *, |
|
133 unsigned int , unsigned long ); |
|
134 static int me8100_fasync(int, struct file *, int); |
|
135 static void me8100_isr(int, void *, struct pt_regs *); |
|
136 |
|
137 static int me8100_init_board(me8100_info_type *, struct pci_dev *); |
|
138 static int me8100_reset_board(me8100_info_type *); |
|
139 |
|
140 static int me8100_read_id_a(unsigned short *, me8100_info_type *); |
|
141 static int me8100_write_ctrl_a(unsigned short *, me8100_info_type *); |
|
142 static int me8100_res_int_a(me8100_info_type *); |
|
143 static int me8100_read_di_a(unsigned short *, me8100_info_type *); |
|
144 static int me8100_write_do_a(unsigned short *, me8100_info_type *); |
|
145 static int me8100_write_pattern_a(unsigned short *, me8100_info_type *); |
|
146 static int me8100_write_mask_a(unsigned short *, me8100_info_type *); |
|
147 static int me8100_read_int_di_a(unsigned short *, me8100_info_type *); |
|
148 |
|
149 static int me8100_read_id_b(unsigned short *, me8100_info_type *); |
|
150 static int me8100_write_ctrl_b(unsigned short *, me8100_info_type *); |
|
151 static int me8100_res_int_b(me8100_info_type *); |
|
152 static int me8100_read_di_b(unsigned short *, me8100_info_type *); |
|
153 static int me8100_write_do_b(unsigned short *, me8100_info_type *); |
|
154 static int me8100_write_pattern_b(unsigned short *, me8100_info_type *); |
|
155 static int me8100_write_mask_b(unsigned short *, me8100_info_type *); |
|
156 static int me8100_read_int_di_b(unsigned short *, me8100_info_type *); |
|
157 |
|
158 static int me8100_write_counter_0(unsigned char *, me8100_info_type *); |
|
159 static int me8100_write_counter_1(unsigned char *, me8100_info_type *); |
|
160 static int me8100_write_counter_2(unsigned char *, me8100_info_type *); |
|
161 static int me8100_read_counter_0(unsigned char *, me8100_info_type *); |
|
162 static int me8100_read_counter_1(unsigned char *, me8100_info_type *); |
|
163 static int me8100_read_counter_2(unsigned char *, me8100_info_type *); |
|
164 static int me8100_setup_counter(unsigned char *, me8100_info_type *); |
|
165 |
|
166 static int me8100_get_serial(unsigned int *, me8100_info_type *); |
|
167 static int me8100_get_name(me8100_version_enum_type *, me8100_info_type *); |
|
168 static int me8100_int_occur(me8100_int_occur_type *, me8100_info_type *); |
|
169 static int me8100_setup_icsr(unsigned char *, me8100_info_type *); |
|
170 static int me8100_read_icsr(unsigned char *, me8100_info_type *); |
|
171 static int me8100_get_board_info(me8100_info_type *, me8100_info_type *); |
|
172 static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_type *); |
|
173 |
|
174 |
|
175 /* File operations provided by the driver */ |
|
176 static struct file_operations me8100_file_operations = { |
|
177 #ifdef LINUX_24 |
|
178 THIS_MODULE, /* owner */ |
|
179 #endif |
|
180 NULL, /* lseek() */ |
|
181 NULL, /* read() */ |
|
182 NULL, /* write() */ |
|
183 NULL, /* readdir() */ |
|
184 NULL, /* poll() */ |
|
185 me8100_ioctl, /* ioctl() */ |
|
186 NULL, /* mmap() */ |
|
187 me8100_open, /* open() */ |
|
188 NULL, /* flush() */ |
|
189 me8100_release, /* release() */ |
|
190 NULL, /* fsync() */ |
|
191 me8100_fasync, /* fasync() */ |
|
192 NULL, /* check_media_change()*/ |
|
193 NULL, /* revalidate() */ |
|
194 NULL /* lock() */ |
|
195 }; |
|
196 |
|
197 |
|
198 |
|
199 /* |
|
200 * Routine: |
|
201 * init_module |
|
202 * |
|
203 * Description: |
|
204 * This function is executed from the system, when the driver is loaded. |
|
205 * Actions performed: |
|
206 * - Searches for PCI hardware. |
|
207 * - Initializes detected ME8100 boards with me8100_init_board(). |
|
208 * - Installs the driver in the system with register_chrdev(). |
|
209 * |
|
210 * Parameter list: |
|
211 * Name Type Access Description |
|
212 *-------------------------------------------------------------------------- |
|
213 * |
|
214 * Result: |
|
215 * On success the return value is 0, else is failure. |
|
216 *-------------------------------------------------------------------------- |
|
217 * Author: GG |
|
218 * Modification: |
|
219 */ |
|
220 #ifdef CONFIG_PCI |
|
221 int init_module(void){ |
|
222 int result; |
|
223 unsigned short board_count = 0; |
|
224 unsigned short sort_count; |
|
225 struct pci_dev *pci_dev_ptr = NULL; |
|
226 |
|
227 PDEBUG("init_module() is executed\n"); |
|
228 |
|
229 /* Set the board context to 0 */ |
|
230 memset(&info_vec, 0, sizeof(info_vec)); |
|
231 |
|
232 if (pci_present()){ |
|
233 /* Search for ME8100_A boards */ |
|
234 for(sort_count = 0; |
|
235 sort_count < ME8100_MAX_DEVICES; |
|
236 sort_count++, board_count++){ |
|
237 pci_dev_ptr = pci_find_device(PCI_VENDOR_ID_MEILHAUS, |
|
238 PCI_DEVICE_ID_MEILHAUS_ME8100_A, |
|
239 pci_dev_ptr); |
|
240 if(!pci_dev_ptr) |
|
241 break; |
|
242 |
|
243 PDEBUG("init_module():ME8100_A found\n"); |
|
244 info_vec[board_count].version = ME8100_A; |
|
245 info_vec[board_count].board_count = board_count; |
|
246 |
|
247 result = me8100_init_board(&info_vec[board_count], pci_dev_ptr); |
|
248 if (result){ |
|
249 printk(KERN_ERR"ME8100:init_module():Can't init board\n"); |
|
250 return result; |
|
251 } |
|
252 } |
|
253 |
|
254 /* Search for ME8100_B boards */ |
|
255 for(sort_count = 0; |
|
256 sort_count < ME8100_MAX_DEVICES; |
|
257 sort_count++, board_count++){ |
|
258 pci_dev_ptr = pci_find_device(PCI_VENDOR_ID_MEILHAUS, |
|
259 PCI_DEVICE_ID_MEILHAUS_ME8100_B, |
|
260 pci_dev_ptr); |
|
261 if(!pci_dev_ptr) |
|
262 break; |
|
263 |
|
264 PDEBUG("init_module():ME8100_B found\n"); |
|
265 info_vec[board_count].version = ME8100_B; |
|
266 info_vec[board_count].board_count = board_count; |
|
267 |
|
268 result = me8100_init_board(&info_vec[board_count], pci_dev_ptr); |
|
269 if (result){ |
|
270 printk(KERN_ERR"ME8100:init_module():Can't init board\n"); |
|
271 return result; |
|
272 } |
|
273 } |
|
274 |
|
275 if (board_count == 0){ |
|
276 printk(KERN_ERR"ME8100:init_module():No PCI-Devices found\n"); |
|
277 return -ENODEV; |
|
278 } |
|
279 |
|
280 me8100_board_count = board_count; |
|
281 PDEBUG("init_module(): %d Boards found\n", me8100_board_count); |
|
282 |
|
283 /* |
|
284 * Register the driver in the system with major number = 0. |
|
285 * This means that the major number is automatically assigned |
|
286 * from the kernel and returned as result from register_chrdev(). |
|
287 */ |
|
288 result = register_chrdev(major, ME8100_NAME, &me8100_file_operations); |
|
289 if (result < 0){ |
|
290 printk(KERN_ERR"ME8100:init_module():Can't get major no\n"); |
|
291 return result; |
|
292 } |
|
293 else{ |
|
294 major = result; |
|
295 PDEBUG("init_module():Major = %d\n", major); |
|
296 } |
|
297 } |
|
298 else{ |
|
299 printk(KERN_ERR"ME8100:init_module():No PCI-BIOS present !\n"); |
|
300 return -ENODEV; |
|
301 } |
|
302 return 0; |
|
303 } |
|
304 #else |
|
305 return -ENODEV |
|
306 #endif |
|
307 |
|
308 |
|
309 |
|
310 /* |
|
311 * Routine: |
|
312 * me8100_init_board |
|
313 * |
|
314 * Description: |
|
315 * This function initializes the detected me8100 boards. |
|
316 * Actions performed: |
|
317 * - Get the baseaddresses of the PLX and the ME8100. |
|
318 * - If PLX bug detected, start workaround. |
|
319 * - Initializes the device info structure. |
|
320 * - Resets the board with me8100_reset_board(). |
|
321 * |
|
322 * Parameter list: |
|
323 * Name Type Access Description |
|
324 *-------------------------------------------------------------------------- |
|
325 * *pci_dev_ptr struct pci_dev read List with all pci devices. |
|
326 * *info me8100_info_type read Global board context. |
|
327 * |
|
328 * Result: |
|
329 * On success the return value is 0, else failure. |
|
330 *-------------------------------------------------------------------------- |
|
331 * Author: GG |
|
332 * |
|
333 * Modification: |
|
334 * 01.09.14 Don't get baseaddresses from struct pci_dev, |
|
335 * for compatibility. (GG) |
|
336 * |
|
337 */ |
|
338 static int me8100_init_board(me8100_info_type *info, |
|
339 struct pci_dev *pci_dev_ptr){ |
|
340 int result = 0; |
|
341 unsigned int plx_regbase_tmp; |
|
342 unsigned int me8100_regbase_tmp; |
|
343 unsigned int swap_regbase_tmp; |
|
344 unsigned int regbase_tmp; |
|
345 |
|
346 PDEBUG("me8100_init_board() is executed\n"); |
|
347 |
|
348 |
|
349 /*--------------------------- plx regbase ---------------------------------*/ |
|
350 |
|
351 result = pci_read_config_dword(pci_dev_ptr, |
|
352 PCI_BASE_ADDRESS_1, |
|
353 &plx_regbase_tmp); |
|
354 if(result != PCIBIOS_SUCCESSFUL){ |
|
355 printk(KERN_ERR"ME8100:Can't get PCI_BASE_ADDRESS_1\n"); |
|
356 return result; |
|
357 } |
|
358 PDEBUG("me8100_init_board():PCI base 0 = 0x%04X\n", plx_regbase_tmp); |
|
359 |
|
360 result = pci_read_config_dword(pci_dev_ptr, |
|
361 PCI_BASE_ADDRESS_5, |
|
362 &swap_regbase_tmp); |
|
363 if(result != PCIBIOS_SUCCESSFUL){ |
|
364 printk(KERN_ERR"ME8100:Can't get PCI_BASE_ADDRESS_5\n"); |
|
365 return result; |
|
366 } |
|
367 PDEBUG("me8100_init_board():PCI base 5 = 0x%04X\n", swap_regbase_tmp); |
|
368 |
|
369 if(!swap_regbase_tmp){ |
|
370 printk(KERN_WARNING"ME8100:me8100_init_board:Swap not present\n"); |
|
371 } |
|
372 |
|
373 /* |
|
374 * This is the PLX bug workaround. |
|
375 * If bit 7 is set in the plx_regbase, |
|
376 * the plx registers maybe not readable. |
|
377 */ |
|
378 if(plx_regbase_tmp & 0x0080){ |
|
379 printk(KERN_WARNING"ME8100:me8100_init_board():PLX-BUG detected\n"); |
|
380 |
|
381 if(PLX_WORKAROUND_ENABLE){ |
|
382 if(swap_regbase_tmp){ |
|
383 regbase_tmp = plx_regbase_tmp; |
|
384 plx_regbase_tmp = swap_regbase_tmp; |
|
385 swap_regbase_tmp = regbase_tmp; |
|
386 result = pci_write_config_dword(pci_dev_ptr, |
|
387 PCI_BASE_ADDRESS_1, |
|
388 plx_regbase_tmp); |
|
389 if(result != PCIBIOS_SUCCESSFUL) |
|
390 return result; |
|
391 |
|
392 result = pci_write_config_dword(pci_dev_ptr, |
|
393 PCI_BASE_ADDRESS_5, |
|
394 swap_regbase_tmp); |
|
395 if(result != PCIBIOS_SUCCESSFUL) |
|
396 return result; |
|
397 } |
|
398 else{ |
|
399 plx_regbase_tmp -= 0x80; |
|
400 result = pci_write_config_dword(pci_dev_ptr, |
|
401 PCI_BASE_ADDRESS_1, |
|
402 plx_regbase_tmp); |
|
403 if(result != PCIBIOS_SUCCESSFUL) |
|
404 return result; |
|
405 } |
|
406 } |
|
407 } |
|
408 |
|
409 if(!(plx_regbase_tmp & PCI_BASE_ADDRESS_SPACE)){ |
|
410 printk(KERN_ERR"ME8100:me8100_init_board():PLX space is not MEM\n"); |
|
411 return -EIO; |
|
412 } |
|
413 info->plx_regbase_size = PLX_BASE_SIZE; |
|
414 info->plx_regbase = plx_regbase_tmp & PCI_BASE_ADDRESS_IO_MASK; |
|
415 PDEBUG("me8100_init_board():IO at 0x%04X\n", info->plx_regbase); |
|
416 |
|
417 |
|
418 /*--------------------------- me8100 regbase ------------------------------*/ |
|
419 |
|
420 result = pci_read_config_dword(pci_dev_ptr, |
|
421 PCI_BASE_ADDRESS_2, |
|
422 &me8100_regbase_tmp); |
|
423 if(result != PCIBIOS_SUCCESSFUL){ |
|
424 printk(KERN_ERR"ME8100:Can't get PCI_BASE_ADDRESS_2\n"); |
|
425 return result; |
|
426 } |
|
427 PDEBUG("me8100_init_board():PCI base 2 = 0x%04X\n", me8100_regbase_tmp); |
|
428 |
|
429 if(!(me8100_regbase_tmp & PCI_BASE_ADDRESS_SPACE)){ |
|
430 printk(KERN_ERR"ME8100:me8100_init_board():ME8100 space is not IO\n"); |
|
431 return -EIO; |
|
432 } |
|
433 info->me8100_regbase_size = ME8100_BASE_SIZE; |
|
434 info->me8100_regbase = me8100_regbase_tmp & PCI_BASE_ADDRESS_IO_MASK; |
|
435 PDEBUG("me8100_init_board():IO at 0x%04X\n", info->me8100_regbase); |
|
436 |
|
437 |
|
438 /*--------------------------- init device info ----------------------------*/ |
|
439 |
|
440 result = pci_read_config_dword(pci_dev_ptr, 0x2C, &info->serial_no); |
|
441 if(result != PCIBIOS_SUCCESSFUL){ |
|
442 printk(KERN_ERR"ME8100:me8100_init_board:Can't get serial_no\n"); |
|
443 return result; |
|
444 } |
|
445 PDEBUG("me8100_init_board():serial_no = 0x%08X\n", info->serial_no); |
|
446 |
|
447 result = pci_read_config_byte(pci_dev_ptr, 0x08, &info->hw_revision); |
|
448 if(result != PCIBIOS_SUCCESSFUL){ |
|
449 printk(KERN_ERR"ME8100:me8100_init_board():Can't get hw_revision\n"); |
|
450 return result; |
|
451 } |
|
452 PDEBUG("me8100_init_board():hw_revision = 0x%02X\n", info->hw_revision); |
|
453 |
|
454 info->vendor_id = pci_dev_ptr->vendor; |
|
455 PDEBUG("me8100_init_board():vendor_id = 0x%04X\n", info->vendor_id); |
|
456 |
|
457 info->device_id = pci_dev_ptr->device; |
|
458 PDEBUG("me8100_init_board():device_id = 0x%04X\n", info->device_id); |
|
459 |
|
460 info->pci_dev_no = PCI_SLOT(pci_dev_ptr->devfn); |
|
461 PDEBUG("me8100_init_board():pci_dev_no = 0x%02X\n", info->pci_dev_no); |
|
462 |
|
463 info->pci_func_no = PCI_FUNC(pci_dev_ptr->devfn); |
|
464 PDEBUG("me8100_init_board():pci_func_no = 0x%02X\n", info->pci_func_no); |
|
465 |
|
466 info->pci_bus_no = pci_dev_ptr->bus->number; |
|
467 PDEBUG("me8100_init_board():pci_bus_no = 0x%02X\n", info->pci_bus_no); |
|
468 |
|
469 info->int_line = pci_dev_ptr->irq; |
|
470 PDEBUG("me8100_init_board():int_line = %d\n", info->int_line); |
|
471 |
|
472 info->int_count_1 = 0; |
|
473 info->int_count_2 = 0; |
|
474 info->int1 = 0; |
|
475 info->int2 = 0; |
|
476 info->file_ptr = NULL; |
|
477 info->board_in_use = 0; |
|
478 spin_lock_init(&info->use_lock); |
|
479 |
|
480 |
|
481 /*--------------------------- Reset the board -----------------------------*/ |
|
482 |
|
483 result = me8100_reset_board(info); |
|
484 if(result){ |
|
485 printk(KERN_ERR"ME8100:me8100_init_board():Can't reset board\n"); |
|
486 return result; |
|
487 } |
|
488 |
|
489 return 0; |
|
490 } |
|
491 |
|
492 |
|
493 |
|
494 /* |
|
495 * Routine: |
|
496 * me8100_reset_board |
|
497 * |
|
498 * Description: |
|
499 * This function resets the ME-81000 board. |
|
500 * Actions performed: |
|
501 * - Disables the interruptlogic of the plx. |
|
502 * - Disables the interrupts on the ME-8100. |
|
503 * - Sets the digital I/O to high impedance. |
|
504 * |
|
505 * Parameter list: |
|
506 * Name Type Access Description |
|
507 *-------------------------------------------------------------------------- |
|
508 * board_count int read Index of the detected board |
|
509 * |
|
510 * Result: |
|
511 * On success the return value is 0, else is failure. |
|
512 *-------------------------------------------------------------------------- |
|
513 * Author: GG |
|
514 * Modification: |
|
515 */ |
|
516 static int me8100_reset_board(me8100_info_type *info){ |
|
517 unsigned char icsr = 0x12; |
|
518 |
|
519 PDEBUG("me8100_reset_board() is executed\n"); |
|
520 |
|
521 /* Disable the Interrupt logic of the plx */ |
|
522 PDEBUG("me8100_reset_board(): plx_mode = 0x%X\n", icsr); |
|
523 outb(icsr, info->plx_regbase + PLX_ICSR); |
|
524 |
|
525 /* Ports to high impedance, interrupts deactivated */ |
|
526 outw(0x00, info->me8100_regbase + ME8100_CTRL_REG_A); |
|
527 outw(0x0000, info->me8100_regbase + ME8100_CTRL_REG_B); |
|
528 |
|
529 /* Reset any pending interrupt */ |
|
530 inw(info->me8100_regbase + ME8100_RES_INT_REG_A); |
|
531 inw(info->me8100_regbase + ME8100_RES_INT_REG_B); |
|
532 |
|
533 return 0; |
|
534 } |
|
535 |
|
536 |
|
537 |
|
538 /* |
|
539 * Routine: |
|
540 * me8100_open |
|
541 * |
|
542 * Description: |
|
543 * Function, which is executed, when a userprogramm makes the syscall |
|
544 * open. |
|
545 * Actions performed: |
|
546 * - It installs the drivers interrupt service routine |
|
547 * me8100_isr in the system. |
|
548 * - It remarks the board as used in the global data structure. |
|
549 * |
|
550 * Parameter list: |
|
551 * Name Type Access Description |
|
552 *-------------------------------------------------------------------------- |
|
553 * *inode_ptr struct inode read Pointer to device inode. |
|
554 * *file_ptr struct file read Ponnter to file structure. |
|
555 * |
|
556 *-------------------------------------------------------------------------- |
|
557 * |
|
558 * Result: |
|
559 * On success the return value is 0 else failure. |
|
560 *-------------------------------------------------------------------------- |
|
561 * Author: GG |
|
562 * Modification: |
|
563 * 01.10.04 Guard board_in_use with spin_lock, cause of race condition |
|
564 * when compiling for SMP. |
|
565 */ |
|
566 static int me8100_open(struct inode *inode_ptr, struct file *file_ptr){ |
|
567 int minor = 0; |
|
568 int err = 0; |
|
569 |
|
570 PDEBUG("me8100_open() is executed\n"); |
|
571 |
|
572 minor = MINOR(inode_ptr->i_rdev); |
|
573 |
|
574 if(minor >= me8100_board_count){ |
|
575 printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", minor); |
|
576 return -ENODEV; |
|
577 } |
|
578 |
|
579 spin_lock(&info_vec[minor].use_lock); |
|
580 if(info_vec[minor].board_in_use){ |
|
581 printk(KERN_ERR"ME8100:me8100_open():Board %d already in use\n", minor); |
|
582 spin_unlock(&info_vec[minor].use_lock); |
|
583 return -EBUSY; |
|
584 } |
|
585 info_vec[minor].board_in_use = 1; |
|
586 spin_unlock(&info_vec[minor].use_lock); |
|
587 |
|
588 info_vec[minor].file_ptr = file_ptr; |
|
589 |
|
590 err = request_irq(info_vec[minor].int_line, |
|
591 me8100_isr, |
|
592 SA_INTERRUPT | SA_SHIRQ, |
|
593 ME8100_NAME, |
|
594 (void *)&info_vec[minor]); |
|
595 if(err){ |
|
596 printk(KERN_ERR"ME8100:me8100_open():Can't get interrupt line"); |
|
597 return err; |
|
598 } |
|
599 |
|
600 MOD_INC_USE_COUNT; |
|
601 |
|
602 return 0; |
|
603 } |
|
604 |
|
605 |
|
606 |
|
607 /* |
|
608 * Routine: |
|
609 * me8100_release |
|
610 * |
|
611 * Description: |
|
612 * Function, which is executed, when the userprogramm makes the syscall |
|
613 * close. First it resets the board and marks the board as unused in the |
|
614 * global info_vec. Then it frees the Interrupt requested |
|
615 * in me8100_open. After that the fasync queue probably installed is |
|
616 * deleted. |
|
617 * At last the usecount of the path is decremented. |
|
618 * |
|
619 * Parameter list: |
|
620 * Name Type Access Description |
|
621 *-------------------------------------------------------------------------- |
|
622 * inode_ptr struct inode * read pointer to the inode structure of |
|
623 * the system |
|
624 * file_ptr struct file * read pointer to the file structure of |
|
625 * the system |
|
626 * |
|
627 * Result: |
|
628 * On success the return value is 0, else is failure |
|
629 *-------------------------------------------------------------------------- |
|
630 * Author: GG |
|
631 * Modification: |
|
632 */ |
|
633 static int me8100_release(struct inode *inode_ptr, struct file *file_ptr){ |
|
634 int minor = 0; |
|
635 int err = 0; |
|
636 |
|
637 PDEBUG("me8100_release() is executed\n"); |
|
638 |
|
639 minor = MINOR(inode_ptr->i_rdev); |
|
640 |
|
641 err = me8100_reset_board(&info_vec[minor]); |
|
642 if(err){ |
|
643 printk(KERN_ERR"ME8100:me8100_release():Can't reset"); |
|
644 return err; |
|
645 } |
|
646 |
|
647 free_irq(info_vec[minor].int_line, (void *) &info_vec[minor]); |
|
648 |
|
649 /* Delete the fasync structure and free memory */ |
|
650 me8100_fasync(0, file_ptr, 0); |
|
651 |
|
652 info_vec[minor].board_in_use = 0; |
|
653 |
|
654 MOD_DEC_USE_COUNT; |
|
655 PDEBUG("me8100_release() is leaved\n"); |
|
656 return 0; |
|
657 } |
|
658 |
|
659 |
|
660 |
|
661 /* |
|
662 * Routine: |
|
663 * me8100_ioctl |
|
664 * |
|
665 * Description: |
|
666 * Function, which prvides the functionality of the ME8100 board. This |
|
667 * function is executed, when a user program executes the systemcall |
|
668 * ioctl. It checks if the service requested is valid and calls the |
|
669 * appropriate routine to handle the request. |
|
670 * |
|
671 * Parameter list: |
|
672 * Name Type Access Description |
|
673 *-------------------------------------------------------------------------- |
|
674 * inode_ptr struct inode * read pointer to the inode structure of |
|
675 * the system |
|
676 * file_ptr struct file * read pointer to the file structure of |
|
677 * the system |
|
678 * service unsigned int read requested service |
|
679 * arg unsigned long r/w address of the structure with |
|
680 * user data and parameters |
|
681 * |
|
682 * Result: |
|
683 * On success the return value is 0, else is failure |
|
684 *-------------------------------------------------------------------------- |
|
685 * Author: GG |
|
686 * Modification: |
|
687 * 01.02.14 GG Add new ioctls: |
|
688 * get_board_info |
|
689 * get_int count |
|
690 */ |
|
691 static int me8100_ioctl(struct inode * inode_ptr, |
|
692 struct file *file_ptr, |
|
693 unsigned int service, |
|
694 unsigned long arg){ |
|
695 |
|
696 int minor = 0; |
|
697 |
|
698 PDEBUG("me8100_ioctl() is executed\n"); |
|
699 |
|
700 minor = MINOR(inode_ptr->i_rdev); |
|
701 |
|
702 if(_IOC_TYPE(service) != ME8100_MAGIC){ |
|
703 printk(KERN_ERR"ME8100:Invalid ME8100_MAGIC\n"); |
|
704 return -EINVAL; |
|
705 } |
|
706 if(_IOC_NR(service) > ME8100_IOCTL_MAXNR){ |
|
707 printk(KERN_ERR"ME8100:Service number ME8100 to high\n"); |
|
708 return -EINVAL; |
|
709 } |
|
710 |
|
711 switch(service){ |
|
712 case ME8100_READ_ID_A: |
|
713 return me8100_read_id_a((unsigned short *) arg, &info_vec[minor]); |
|
714 case ME8100_WRITE_CTRL_A: |
|
715 return me8100_write_ctrl_a((unsigned short *) arg, &info_vec[minor]); |
|
716 case ME8100_RES_INT_A: |
|
717 return me8100_res_int_a(&info_vec[minor]); |
|
718 case ME8100_READ_DI_A: |
|
719 return me8100_read_di_a((unsigned short *) arg, &info_vec[minor]); |
|
720 case ME8100_WRITE_DO_A: |
|
721 return me8100_write_do_a((unsigned short *) arg, &info_vec[minor]); |
|
722 case ME8100_WRITE_PATTERN_A: |
|
723 return me8100_write_pattern_a((unsigned short *) arg, &info_vec[minor]); |
|
724 case ME8100_WRITE_MASK_A: |
|
725 return me8100_write_mask_a((unsigned short *) arg, &info_vec[minor]); |
|
726 case ME8100_READ_INT_DI_A: |
|
727 return me8100_read_int_di_a((unsigned short *) arg, &info_vec[minor]); |
|
728 case ME8100_READ_ID_B: |
|
729 return me8100_read_id_b((unsigned short *) arg, &info_vec[minor]); |
|
730 case ME8100_WRITE_CTRL_B: |
|
731 return me8100_write_ctrl_b((unsigned short *) arg, &info_vec[minor]); |
|
732 case ME8100_RES_INT_B: |
|
733 return me8100_res_int_b(&info_vec[minor]); |
|
734 case ME8100_READ_DI_B: |
|
735 return me8100_read_di_b((unsigned short *) arg, &info_vec[minor]); |
|
736 case ME8100_WRITE_DO_B: |
|
737 return me8100_write_do_b((unsigned short *) arg, &info_vec[minor]); |
|
738 case ME8100_WRITE_PATTERN_B: |
|
739 return me8100_write_pattern_b((unsigned short *) arg, &info_vec[minor]); |
|
740 case ME8100_WRITE_MASK_B: |
|
741 return me8100_write_mask_b((unsigned short *) arg, &info_vec[minor]); |
|
742 case ME8100_READ_INT_DI_B: |
|
743 return me8100_read_int_di_b((unsigned short *) arg, &info_vec[minor]); |
|
744 case ME8100_WRITE_COUNTER_0: |
|
745 return me8100_write_counter_0((unsigned char *) arg, &info_vec[minor]); |
|
746 case ME8100_WRITE_COUNTER_1: |
|
747 return me8100_write_counter_1((unsigned char *) arg, &info_vec[minor]); |
|
748 case ME8100_WRITE_COUNTER_2: |
|
749 return me8100_write_counter_2((unsigned char *) arg, &info_vec[minor]); |
|
750 case ME8100_READ_COUNTER_0: |
|
751 return me8100_read_counter_0((unsigned char *) arg, &info_vec[minor]); |
|
752 case ME8100_READ_COUNTER_1: |
|
753 return me8100_read_counter_1((unsigned char *) arg, &info_vec[minor]); |
|
754 case ME8100_READ_COUNTER_2: |
|
755 return me8100_read_counter_2((unsigned char *) arg, &info_vec[minor]); |
|
756 case ME8100_SETUP_COUNTER: |
|
757 return me8100_setup_counter((unsigned char *) arg, &info_vec[minor]); |
|
758 case ME8100_GET_SERIAL: |
|
759 return me8100_get_serial((unsigned int *) arg, &info_vec[minor]); |
|
760 case ME8100_GET_NAME: |
|
761 return me8100_get_name((me8100_version_enum_type *) arg, &info_vec[minor]); |
|
762 case ME8100_INT_OCCUR: |
|
763 return me8100_int_occur((me8100_int_occur_type *) arg, &info_vec[minor]); |
|
764 case ME8100_SETUP_ICSR: |
|
765 return me8100_setup_icsr((unsigned char *) arg, &info_vec[minor]); |
|
766 case ME8100_READ_ICSR: |
|
767 return me8100_read_icsr((unsigned char *) arg, &info_vec[minor]); |
|
768 case ME8100_GET_BOARD_INFO: |
|
769 return me8100_get_board_info((me8100_info_type *)arg, &info_vec[minor]); |
|
770 case ME8100_GET_INT_COUNT: |
|
771 return me8100_get_int_count((me8100_int_occur_type *)arg,&info_vec[minor]); |
|
772 default: |
|
773 return -EINVAL; |
|
774 } |
|
775 |
|
776 return 0; |
|
777 } |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 /* |
|
783 * Routine: |
|
784 * me8100_fasync |
|
785 * |
|
786 * Description: |
|
787 * This function is executed, when a user program executes the systemcall |
|
788 * fcntl. It remarks the processes who want to be informed asynchronous |
|
789 * in a fasync structure and saves the pointer to this structure in the |
|
790 * file structure of the path. |
|
791 * |
|
792 * Parameter list: |
|
793 * Name Type Access Description |
|
794 *-------------------------------------------------------------------------- |
|
795 * fd int read File descriptor of the open path. |
|
796 * file_ptr struct file * read Pointer to the file structure of |
|
797 * the system. |
|
798 * mode int read Requested operation, |
|
799 * passed to the fasync_helper. |
|
800 * |
|
801 * Result: |
|
802 * All < 0 marks a failure. |
|
803 *-------------------------------------------------------------------------- |
|
804 * Author: GG |
|
805 * Modufication: |
|
806 */ |
|
807 static int me8100_fasync(int fd, struct file *file_ptr, int mode){ |
|
808 int val = 0; |
|
809 struct fasync_struct *fasync_ptr; |
|
810 |
|
811 fasync_ptr = file_ptr->private_data; |
|
812 |
|
813 PDEBUG("me8100_fasync() is executed\n"); |
|
814 |
|
815 val = fasync_helper(fd, file_ptr, mode, &fasync_ptr); |
|
816 file_ptr->private_data = fasync_ptr; |
|
817 return val; |
|
818 } |
|
819 |
|
820 |
|
821 |
|
822 |
|
823 /* |
|
824 * Routine: |
|
825 * me8100_get_board_info |
|
826 * |
|
827 * Description: |
|
828 * This function is called by me8100_ioctl, in order to get the global |
|
829 * variables for a specific board from the info_vec. |
|
830 * Parameter list: |
|
831 * Name Type Access Description |
|
832 *-------------------------------------------------------------------------- |
|
833 * *arg me8100_info_type w Carries the value to user. |
|
834 * *info me8100_info_type r Global board context. |
|
835 * |
|
836 * Result: |
|
837 * On success the return value is 0, else is failure. |
|
838 *-------------------------------------------------------------------------- |
|
839 * Author: GG |
|
840 * Modification: |
|
841 */ |
|
842 static int me8100_get_board_info(me8100_info_type *arg, |
|
843 me8100_info_type *info){ |
|
844 |
|
845 PDEBUG("me8100_get_board_info() is executed\n"); |
|
846 |
|
847 if(copy_to_user(arg, info, sizeof(me8100_info_type))) |
|
848 return -EFAULT; |
|
849 return 0; |
|
850 } |
|
851 |
|
852 |
|
853 |
|
854 |
|
855 /* |
|
856 * Routine: |
|
857 * me8100_read_id_a |
|
858 * |
|
859 * Description: |
|
860 * This function is called by the me8100_ioctl, in order to read the |
|
861 * function id register a. |
|
862 * |
|
863 * Parameter list: |
|
864 * Name Type Access Description |
|
865 *-------------------------------------------------------------------------- |
|
866 * *arg unsigned short w Carries the value to user. |
|
867 * *info me8100_info_type r Global board context. |
|
868 * |
|
869 * Result: |
|
870 * On success the return value is 0, else is failure. |
|
871 *-------------------------------------------------------------------------- |
|
872 * Author: GG |
|
873 * Modification: |
|
874 */ |
|
875 static int me8100_read_id_a(unsigned short *arg, me8100_info_type *info){ |
|
876 int err = 0; |
|
877 unsigned short id_a; |
|
878 |
|
879 PDEBUG("me8100_read_id_a() is executed\n"); |
|
880 |
|
881 id_a = inw(info->me8100_regbase + ME8100_ID_REG_A); |
|
882 err = copy_to_user(arg, &id_a, sizeof(id_a)); |
|
883 if(err) |
|
884 return err; |
|
885 |
|
886 return 0; |
|
887 } |
|
888 |
|
889 |
|
890 |
|
891 |
|
892 |
|
893 /* |
|
894 * Routine: |
|
895 * me8100_write_ctrl_a |
|
896 * |
|
897 * Description: |
|
898 * This function is called by the me8100_ioctl, in order to setup the |
|
899 * CTRL register a. |
|
900 * |
|
901 * Parameter list: |
|
902 * Name Type Access Description |
|
903 *-------------------------------------------------------------------------- |
|
904 * *arg unsigned short r Carries the value from user. |
|
905 * *info me8100_info_type r Global board context. |
|
906 * |
|
907 * Result: |
|
908 * On success the return value is 0, else is failure. |
|
909 *-------------------------------------------------------------------------- |
|
910 * Author: GG |
|
911 * Modification: |
|
912 */ |
|
913 static int me8100_write_ctrl_a(unsigned short *arg, me8100_info_type *info){ |
|
914 int err = 0; |
|
915 unsigned short ctrl_a = 0; |
|
916 |
|
917 PDEBUG("me8100_write_ctrl_a() is executed\n"); |
|
918 |
|
919 err = copy_from_user(&ctrl_a, arg, sizeof(ctrl_a)); |
|
920 if(err) |
|
921 return err; |
|
922 |
|
923 PDEBUG("me8100_write_ctrl_a:ctrl_a=0x%04X\n", ctrl_a); |
|
924 PDEBUG("me8100_write_ctrl_a:To offset=0x%02X\n", ME8100_CTRL_REG_A); |
|
925 outw(ctrl_a, info->me8100_regbase + ME8100_CTRL_REG_A); |
|
926 |
|
927 return 0; |
|
928 } |
|
929 |
|
930 |
|
931 |
|
932 |
|
933 /* |
|
934 * Routine: |
|
935 * me8100_res_int_a |
|
936 * |
|
937 * Description: |
|
938 * This function is called by the me8100_ioctl, in order to reset the |
|
939 * INTR bit a. |
|
940 * |
|
941 * Parameter list: |
|
942 * Name Type Access Description |
|
943 *-------------------------------------------------------------------------- |
|
944 * *info me8100_info_type r Global board context. |
|
945 * |
|
946 * Result: |
|
947 * On success the return value is 0, else is failure. |
|
948 *-------------------------------------------------------------------------- |
|
949 * Author: GG |
|
950 * Modification: |
|
951 */ |
|
952 static int me8100_res_int_a(me8100_info_type *info){ |
|
953 |
|
954 PDEBUG("me8100_res_int_a() is executed\n"); |
|
955 |
|
956 inw(info->me8100_regbase + ME8100_RES_INT_REG_A); |
|
957 |
|
958 return 0; |
|
959 } |
|
960 |
|
961 |
|
962 |
|
963 |
|
964 /* |
|
965 * Routine: |
|
966 * me8100_read_di_a |
|
967 * |
|
968 * Description: |
|
969 * This function is called by the me8100_ioctl, in order to read a value |
|
970 * from the digital input a. |
|
971 * |
|
972 * Parameter list: |
|
973 * Name Type Access Description |
|
974 *-------------------------------------------------------------------------- |
|
975 * *arg unsigned short w Carries the value to user. |
|
976 * *info me8100_info_type r Global board context. |
|
977 * |
|
978 * Result: |
|
979 * On success the return value is 0, else is failure. |
|
980 *-------------------------------------------------------------------------- |
|
981 * Author: GG |
|
982 * Modification: |
|
983 */ |
|
984 static int me8100_read_di_a(unsigned short *arg, me8100_info_type *info){ |
|
985 int err = 0; |
|
986 unsigned short di_a; |
|
987 |
|
988 PDEBUG("me8100_read_di_a() is executed\n"); |
|
989 |
|
990 di_a = inw(info->me8100_regbase + ME8100_DI_REG_A); |
|
991 err = copy_to_user(arg, &di_a, sizeof(di_a)); |
|
992 if(err) |
|
993 return err; |
|
994 |
|
995 return 0; |
|
996 } |
|
997 |
|
998 |
|
999 |
|
1000 |
|
1001 /* |
|
1002 * Routine: |
|
1003 * me8100_write_do_a |
|
1004 * |
|
1005 * Description: |
|
1006 * This function is called by the me8100_ioctl, in order to write a value |
|
1007 * to the digital output a. |
|
1008 * |
|
1009 * Parameter list: |
|
1010 * Name Type Access Description |
|
1011 *-------------------------------------------------------------------------- |
|
1012 * *arg unsigned short r Carries the value from user. |
|
1013 * *info me8100_info_type r Global board context. |
|
1014 * |
|
1015 * Result: |
|
1016 * On success the return value is 0, else is failure |
|
1017 *-------------------------------------------------------------------------- |
|
1018 * Author: GG |
|
1019 * Modification: |
|
1020 */ |
|
1021 static int me8100_write_do_a(unsigned short *arg, me8100_info_type *info){ |
|
1022 int err = 0; |
|
1023 unsigned short do_a = 0; |
|
1024 |
|
1025 PDEBUG("me8100_write_do_a() is executed\n"); |
|
1026 |
|
1027 err = copy_from_user(&do_a, arg, sizeof(do_a)); |
|
1028 if(err) |
|
1029 return err; |
|
1030 |
|
1031 PDEBUG("me8100_write_do_a:do_a=0x%04X\n", do_a); |
|
1032 PDEBUG("me8100_write_do_a:To offset=0x%02X\n", ME8100_DO_REG_A); |
|
1033 outw(do_a, info->me8100_regbase + ME8100_DO_REG_A); |
|
1034 |
|
1035 return 0; |
|
1036 } |
|
1037 |
|
1038 |
|
1039 |
|
1040 /* |
|
1041 * Routine: |
|
1042 * me8100_write_pattern_a |
|
1043 * |
|
1044 * Description: |
|
1045 * This function is called by the me8100_ioctl, in order to setup the |
|
1046 * pattern register a. |
|
1047 * |
|
1048 * Parameter list: |
|
1049 * Name Type Access Description |
|
1050 *-------------------------------------------------------------------------- |
|
1051 * *arg unsigned short r Carries the value from user. |
|
1052 * *info me8100_info_type r Global board context. |
|
1053 * |
|
1054 * Result: |
|
1055 * On success the return value is 0, else is failure. |
|
1056 *-------------------------------------------------------------------------- |
|
1057 * Author: GG |
|
1058 * Modification: |
|
1059 */ |
|
1060 static int me8100_write_pattern_a(unsigned short *arg, me8100_info_type *info){ |
|
1061 int err = 0; |
|
1062 unsigned short pattern_a = 0; |
|
1063 |
|
1064 PDEBUG("me8100_write_pattern_a() is executed\n"); |
|
1065 |
|
1066 err = copy_from_user(&pattern_a, arg, sizeof(pattern_a)); |
|
1067 if(err) |
|
1068 return err; |
|
1069 |
|
1070 PDEBUG("me8100_write_pattern_a:pattern_a=0x%04X\n", pattern_a); |
|
1071 PDEBUG("me8100_write_pattern_a:To offset=0x%02X\n", |
|
1072 ME8100_PATTERN_REG_A); |
|
1073 outw(pattern_a, info->me8100_regbase + ME8100_PATTERN_REG_A); |
|
1074 |
|
1075 return 0; |
|
1076 } |
|
1077 |
|
1078 |
|
1079 |
|
1080 /* |
|
1081 * Routine: |
|
1082 * me8100_write_mask_a |
|
1083 * |
|
1084 * Description: |
|
1085 * This function is called by the me8100_ioctl, in order to setup the |
|
1086 * mask register a. |
|
1087 * |
|
1088 * Parameter list: |
|
1089 * Name Type Access Description |
|
1090 *-------------------------------------------------------------------------- |
|
1091 * *arg unsigned short r Carries the value from user. |
|
1092 * *info me8100_info_type r Global board context. |
|
1093 * |
|
1094 * Result: |
|
1095 * On success the return value is 0, else is failure. |
|
1096 *-------------------------------------------------------------------------- |
|
1097 * Author: GG |
|
1098 * Modification: |
|
1099 */ |
|
1100 static int me8100_write_mask_a(unsigned short *arg, me8100_info_type *info){ |
|
1101 int err = 0; |
|
1102 unsigned short mask_a = 0; |
|
1103 |
|
1104 PDEBUG("me8100_write_mask_a() is executed\n"); |
|
1105 |
|
1106 err = copy_from_user(&mask_a, arg, sizeof(mask_a)); |
|
1107 if(err) |
|
1108 return err; |
|
1109 |
|
1110 PDEBUG("me8100_write_mask_a:mask_a=0x%04X\n", mask_a); |
|
1111 PDEBUG("me8100_write_mask_a:To offset=0x%02X\n", ME8100_MASK_REG_A); |
|
1112 outw(mask_a, info->me8100_regbase + ME8100_MASK_REG_A); |
|
1113 |
|
1114 return 0; |
|
1115 } |
|
1116 |
|
1117 |
|
1118 |
|
1119 |
|
1120 /* |
|
1121 * Routine: |
|
1122 * me8100_read_int_di_a |
|
1123 * |
|
1124 * Description: |
|
1125 * This function is called by the me8100_ioctl, in order to read the |
|
1126 * word from the digital input a, beeing actual at this moment the |
|
1127 * Interrupt rises. |
|
1128 * |
|
1129 * Parameter list: |
|
1130 * Name Type Access Description |
|
1131 *-------------------------------------------------------------------------- |
|
1132 * *arg unsigned short w Carries the value to user. |
|
1133 * *info me8100_info_type r Global board context. |
|
1134 * |
|
1135 * Result: |
|
1136 * On success the return value is 0, else is failure. |
|
1137 *-------------------------------------------------------------------------- |
|
1138 * Author: GG |
|
1139 * Modification: |
|
1140 */ |
|
1141 static int me8100_read_int_di_a(unsigned short *arg, me8100_info_type *info){ |
|
1142 int err = 0; |
|
1143 unsigned short int_di_a; |
|
1144 |
|
1145 PDEBUG("me8100_read_int_di_a() is executed\n"); |
|
1146 |
|
1147 int_di_a = inw(info->me8100_regbase + ME8100_INT_DI_REG_A); |
|
1148 err = copy_to_user(arg, &int_di_a, sizeof(int_di_a)); |
|
1149 if(err){ |
|
1150 PDEBUG("me8100_read_int_di_a:Failed to copy data\n"); |
|
1151 return err; |
|
1152 } |
|
1153 return 0; |
|
1154 } |
|
1155 |
|
1156 |
|
1157 |
|
1158 |
|
1159 |
|
1160 /* |
|
1161 * Routine: |
|
1162 * me8100_read_id_b |
|
1163 * |
|
1164 * Description: |
|
1165 * This function is called by the me8100_ioctl, in order to read the |
|
1166 * function id register b. |
|
1167 * |
|
1168 * Parameter list: |
|
1169 * Name Type Access Description |
|
1170 *-------------------------------------------------------------------------- |
|
1171 * *arg unsigned short w Carries the value to user. |
|
1172 * *info me8100_info_type r Global board context. |
|
1173 * |
|
1174 * Result: |
|
1175 * On success the return value is 0, else is failure. |
|
1176 *-------------------------------------------------------------------------- |
|
1177 * Author: GG |
|
1178 * Modification: |
|
1179 */ |
|
1180 static int me8100_read_id_b(unsigned short *arg, me8100_info_type *info){ |
|
1181 int err = 0; |
|
1182 unsigned short id_b; |
|
1183 |
|
1184 PDEBUG("me8100_read_id_b() is executed\n"); |
|
1185 |
|
1186 id_b = inw(info->me8100_regbase + ME8100_ID_REG_B); |
|
1187 err = copy_to_user(arg, &id_b, sizeof(id_b)); |
|
1188 if(err) |
|
1189 return err; |
|
1190 |
|
1191 return 0; |
|
1192 } |
|
1193 |
|
1194 |
|
1195 |
|
1196 |
|
1197 |
|
1198 /* |
|
1199 * Routine: |
|
1200 * me8100_write_ctrl_b |
|
1201 * |
|
1202 * Description: |
|
1203 * This function is called by the me8100_ioctl, in order to setup the |
|
1204 * CTRL register b. |
|
1205 * |
|
1206 * Parameter list: |
|
1207 * Name Type Access Description |
|
1208 *-------------------------------------------------------------------------- |
|
1209 * arg unsigned short * r carries the value from user |
|
1210 * minor int r specifies the board |
|
1211 * |
|
1212 * Result: |
|
1213 * On success the return value is 0, else is failure. |
|
1214 *-------------------------------------------------------------------------- |
|
1215 * Author: GG |
|
1216 * Modification: |
|
1217 */ |
|
1218 static int me8100_write_ctrl_b(unsigned short *arg, me8100_info_type *info){ |
|
1219 int err = 0; |
|
1220 unsigned short ctrl_b = 0; |
|
1221 |
|
1222 PDEBUG("me8100_write_ctrl_b() is executed\n"); |
|
1223 |
|
1224 err = copy_from_user(&ctrl_b, arg, sizeof(ctrl_b)); |
|
1225 if(err) |
|
1226 return err; |
|
1227 |
|
1228 PDEBUG("me8100_write_ctrl_b:ctrl_b=0x%04X\n", ctrl_b); |
|
1229 PDEBUG("me8100_write_ctrl_b:To offset=0x%02X\n", ME8100_CTRL_REG_B); |
|
1230 outw(ctrl_b, info->me8100_regbase + ME8100_CTRL_REG_B); |
|
1231 |
|
1232 return 0; |
|
1233 } |
|
1234 |
|
1235 |
|
1236 |
|
1237 |
|
1238 /* |
|
1239 * Routine: |
|
1240 * me8100_res_int_b |
|
1241 * |
|
1242 * Description: |
|
1243 * This function is called by the me8100_ioctl, in order to reset the |
|
1244 * INTR bit b. |
|
1245 * |
|
1246 * Parameter list: |
|
1247 * Name Type Access Description |
|
1248 *-------------------------------------------------------------------------- |
|
1249 * *info me8100_info_type r Global board context. |
|
1250 * |
|
1251 * Result: |
|
1252 * On success the return value is 0, else is failure. |
|
1253 *-------------------------------------------------------------------------- |
|
1254 * Author: GG |
|
1255 * Modification: |
|
1256 */ |
|
1257 static int me8100_res_int_b(me8100_info_type *info){ |
|
1258 |
|
1259 PDEBUG("me8100_res_int_b() is executed\n"); |
|
1260 inw(info->me8100_regbase + ME8100_RES_INT_REG_B); |
|
1261 |
|
1262 return 0; |
|
1263 } |
|
1264 |
|
1265 |
|
1266 |
|
1267 |
|
1268 /* |
|
1269 * Routine: |
|
1270 * me8100_read_di_b |
|
1271 * |
|
1272 * Description: |
|
1273 * This function is called by the me8100_ioctl, in order to read a value |
|
1274 * from the digital input b. |
|
1275 * |
|
1276 * Parameter list: |
|
1277 * Name Type Access Description |
|
1278 *-------------------------------------------------------------------------- |
|
1279 * *arg unsigned short w Carries the value to user. |
|
1280 * *info me8100_info_type r Global board context. |
|
1281 * |
|
1282 * Result: |
|
1283 * On success the return value is 0, else is failure. |
|
1284 *-------------------------------------------------------------------------- |
|
1285 * Author: GG |
|
1286 * Modification: |
|
1287 */ |
|
1288 static int me8100_read_di_b(unsigned short *arg, me8100_info_type *info){ |
|
1289 int err = 0; |
|
1290 unsigned short di_b; |
|
1291 |
|
1292 PDEBUG("me8100_read_di_b() is executed\n"); |
|
1293 |
|
1294 di_b = inw(info->me8100_regbase + ME8100_DI_REG_B); |
|
1295 err = copy_to_user(arg, &di_b, sizeof(di_b)); |
|
1296 if(err) |
|
1297 return err; |
|
1298 |
|
1299 return 0; |
|
1300 } |
|
1301 |
|
1302 |
|
1303 |
|
1304 |
|
1305 /* |
|
1306 * Routine: |
|
1307 * me8100_write_do_b |
|
1308 * |
|
1309 * Description: |
|
1310 * This function is called by the me8100_ioctl, in order to write a value |
|
1311 * to the digital output b. |
|
1312 * |
|
1313 * Parameter list: |
|
1314 * Name Type Access Description |
|
1315 *-------------------------------------------------------------------------- |
|
1316 * *arg unsigned short r Carries the value from user. |
|
1317 * *info me8100_info_type r Global board context. |
|
1318 * |
|
1319 * Result: |
|
1320 * On success the return value is 0, else is failure. |
|
1321 *-------------------------------------------------------------------------- |
|
1322 * Author: GG |
|
1323 * Modification: |
|
1324 */ |
|
1325 static int me8100_write_do_b(unsigned short *arg, me8100_info_type *info){ |
|
1326 int err = 0; |
|
1327 unsigned short do_b = 0; |
|
1328 |
|
1329 PDEBUG("me8100_write_do_b() is executed\n"); |
|
1330 |
|
1331 err = copy_from_user(&do_b, arg, sizeof(do_b)); |
|
1332 if(err) |
|
1333 return err; |
|
1334 |
|
1335 PDEBUG("me8100_write_do_b:do_b=0x%04X\n", do_b); |
|
1336 PDEBUG("me8100_write_do_b:To offset=0x%02X\n", ME8100_DO_REG_B); |
|
1337 outw(do_b, info->me8100_regbase + ME8100_DO_REG_B); |
|
1338 |
|
1339 return 0; |
|
1340 } |
|
1341 |
|
1342 |
|
1343 |
|
1344 /* |
|
1345 * Routine: |
|
1346 * me8100_write_pattern_b |
|
1347 * |
|
1348 * Description: |
|
1349 * This function is called by the me8100_ioctl, in order to setup the |
|
1350 * pattern register b. |
|
1351 * |
|
1352 * Parameter list: |
|
1353 * Name Type Access Description |
|
1354 *-------------------------------------------------------------------------- |
|
1355 * *arg unsigned short r Carries the value from user. |
|
1356 * *info me8100_info_type r Global board context. |
|
1357 * |
|
1358 * Result: |
|
1359 * On success the return value is 0, else is failure. |
|
1360 *-------------------------------------------------------------------------- |
|
1361 * Author: GG |
|
1362 * Modification: |
|
1363 */ |
|
1364 static int me8100_write_pattern_b(unsigned short *arg, me8100_info_type *info){ |
|
1365 int err = 0; |
|
1366 unsigned short pattern_b = 0; |
|
1367 |
|
1368 PDEBUG("me8100_write_pattern_b() is executed\n"); |
|
1369 |
|
1370 err = copy_from_user(&pattern_b, arg, sizeof(pattern_b)); |
|
1371 if(err) |
|
1372 return err; |
|
1373 |
|
1374 PDEBUG("me8100_write_pattern_b:pattern_b=0x%04X\n", pattern_b); |
|
1375 PDEBUG("me8100_write_pattern_b:To offset=0x%02X\n", |
|
1376 ME8100_PATTERN_REG_B); |
|
1377 outw(pattern_b, info->me8100_regbase + ME8100_PATTERN_REG_B); |
|
1378 |
|
1379 return 0; |
|
1380 } |
|
1381 |
|
1382 |
|
1383 |
|
1384 /* |
|
1385 * Routine: |
|
1386 * me8100_write_mask_b |
|
1387 * |
|
1388 * Description: |
|
1389 * This function is called by the me8100_ioctl, in order to setup the |
|
1390 * mask register b. |
|
1391 * |
|
1392 * Parameter list: |
|
1393 * Name Type Access Description |
|
1394 *-------------------------------------------------------------------------- |
|
1395 * *arg unsigned short r Carries the value from user. |
|
1396 * *info me8100_info_type r Global board context. |
|
1397 * |
|
1398 * Result: |
|
1399 * On success the return value is 0, else is failure. |
|
1400 *-------------------------------------------------------------------------- |
|
1401 * Author: GG |
|
1402 * Modification: |
|
1403 */ |
|
1404 static int me8100_write_mask_b(unsigned short *arg, me8100_info_type *info){ |
|
1405 int err = 0; |
|
1406 unsigned short mask_b = 0; |
|
1407 |
|
1408 PDEBUG("me8100_write_mask_b() is executed\n"); |
|
1409 |
|
1410 err = copy_from_user(&mask_b, arg, sizeof(mask_b)); |
|
1411 if(err) |
|
1412 return err; |
|
1413 |
|
1414 PDEBUG("me8100_write_mask_b:mask_b=0x%04X\n", mask_b); |
|
1415 PDEBUG("me8100_write_mask_b:To offset=0x%02X\n", ME8100_MASK_REG_B); |
|
1416 outw(mask_b, info->me8100_regbase + ME8100_MASK_REG_B); |
|
1417 |
|
1418 return 0; |
|
1419 } |
|
1420 |
|
1421 |
|
1422 |
|
1423 |
|
1424 /* |
|
1425 * Routine: |
|
1426 * me8100_read_int_di_b |
|
1427 * |
|
1428 * Description: |
|
1429 * This function is called by the me8100_ioctl, in order to read the |
|
1430 * word from the digital input b, beeing actual at the moment the |
|
1431 * Interrupt rises. |
|
1432 * |
|
1433 * Parameter list: |
|
1434 * Name Type Access Description |
|
1435 *-------------------------------------------------------------------------- |
|
1436 * *arg unsigned short w Carries the value to user. |
|
1437 * *info me8100_info_type r Global board context. |
|
1438 * |
|
1439 * Result: |
|
1440 * On success the return value is 0, else is failure. |
|
1441 *-------------------------------------------------------------------------- |
|
1442 * Author: GG |
|
1443 * Modification: |
|
1444 */ |
|
1445 static int me8100_read_int_di_b(unsigned short *arg, me8100_info_type *info){ |
|
1446 int err = 0; |
|
1447 unsigned short int_di_b; |
|
1448 |
|
1449 PDEBUG("me8100_read_int_di_b() is executed\n"); |
|
1450 |
|
1451 int_di_b = inw(info->me8100_regbase + ME8100_INT_DI_REG_B); |
|
1452 err = copy_to_user(arg, &int_di_b, sizeof(int_di_b)); |
|
1453 if(err){ |
|
1454 PDEBUG("me8100_read_int_di_b:Failed to copy data\n"); |
|
1455 return err; |
|
1456 } |
|
1457 return 0; |
|
1458 } |
|
1459 |
|
1460 |
|
1461 |
|
1462 |
|
1463 |
|
1464 /* |
|
1465 * Routine: |
|
1466 * me8100_write_counter_0 |
|
1467 * |
|
1468 * Description: |
|
1469 * This function is called by the me8100_ioctl, in order to write a byte |
|
1470 * to the counter 0 |
|
1471 * |
|
1472 * Parameter list: |
|
1473 * Name Type Access Description |
|
1474 *-------------------------------------------------------------------------- |
|
1475 * *arg unsigned char r Carries the value from user. |
|
1476 * *info me8100_info_type r Global board context. |
|
1477 * |
|
1478 * Result: |
|
1479 * On success the return value is 0, else is failure. |
|
1480 *-------------------------------------------------------------------------- |
|
1481 * Author: GG |
|
1482 * Modification: |
|
1483 */ |
|
1484 static int me8100_write_counter_0(unsigned char *arg, me8100_info_type *info){ |
|
1485 int err = 0; |
|
1486 unsigned char value = 0; |
|
1487 |
|
1488 PDEBUG("me8100_write_counter_0() is executed\n"); |
|
1489 |
|
1490 err = copy_from_user(&value, arg, sizeof(value)); |
|
1491 if(err) |
|
1492 return err; |
|
1493 |
|
1494 PDEBUG("me8100_write_counter_0:counter_0=0x%02X\n", value); |
|
1495 PDEBUG("me8100_write_counter_0:To offset=0x%02X\n", |
|
1496 ME8100_COUNTER_REG_0); |
|
1497 outb(value, info->me8100_regbase + ME8100_COUNTER_REG_0); |
|
1498 |
|
1499 return 0; |
|
1500 } |
|
1501 |
|
1502 |
|
1503 |
|
1504 |
|
1505 |
|
1506 /* |
|
1507 * Routine: |
|
1508 * me8100_write_counter_1 |
|
1509 * |
|
1510 * Description: |
|
1511 * This function is called by the me8100_ioctl, in order to write a byte |
|
1512 * to the counter 1 |
|
1513 * |
|
1514 * Parameter list: |
|
1515 * Name Type Access Description |
|
1516 *-------------------------------------------------------------------------- |
|
1517 * *arg unsigned char r Carries the value from user. |
|
1518 * *info me8100_info_type r Global board context. |
|
1519 * |
|
1520 * Result: |
|
1521 * On success the return value is 0, else is failure. |
|
1522 *-------------------------------------------------------------------------- |
|
1523 * Author: GG |
|
1524 * Modification: |
|
1525 */ |
|
1526 static int me8100_write_counter_1(unsigned char *arg, me8100_info_type *info){ |
|
1527 int err = 0; |
|
1528 unsigned char value = 0; |
|
1529 |
|
1530 PDEBUG("me8100_write_counter_1() is executed\n"); |
|
1531 |
|
1532 err = copy_from_user(&value, arg, sizeof(value)); |
|
1533 if(err) |
|
1534 return err; |
|
1535 |
|
1536 PDEBUG("me8100_write_counter_1:counter_1=0x%02X\n", value); |
|
1537 PDEBUG("me8100_write_counter_1:To offset=0x%02X\n", |
|
1538 ME8100_COUNTER_REG_1); |
|
1539 outb(value, info->me8100_regbase + ME8100_COUNTER_REG_1); |
|
1540 |
|
1541 return 0; |
|
1542 } |
|
1543 |
|
1544 |
|
1545 |
|
1546 |
|
1547 |
|
1548 /* |
|
1549 * Routine: |
|
1550 * me8100_write_counter_2 |
|
1551 * |
|
1552 * Description: |
|
1553 * This function is called by the me8100_ioctl, in order to write a byte |
|
1554 * to the counter 2 |
|
1555 * |
|
1556 * Parameter list: |
|
1557 * Name Type Access Description |
|
1558 *-------------------------------------------------------------------------- |
|
1559 * *arg unsigned char r Carries the value from user. |
|
1560 * *info me8100_info_type r Global board context. |
|
1561 * |
|
1562 * Result: |
|
1563 * On success the return value is 0, else is failure. |
|
1564 *-------------------------------------------------------------------------- |
|
1565 * Author: GG |
|
1566 * Modification: |
|
1567 */ |
|
1568 static int me8100_write_counter_2(unsigned char *arg, me8100_info_type *info){ |
|
1569 int err = 0; |
|
1570 unsigned char value = 0; |
|
1571 |
|
1572 PDEBUG("me8100_write_counter_2() is executed\n"); |
|
1573 |
|
1574 err = copy_from_user(&value, arg, sizeof(value)); |
|
1575 if(err) |
|
1576 return err; |
|
1577 |
|
1578 PDEBUG("me8100_write_counter_2:counter_2=0x%02X\n", value); |
|
1579 PDEBUG("me8100_write_counter_2:To offset=0x%02X\n", |
|
1580 ME8100_COUNTER_REG_2); |
|
1581 outb(value, info->me8100_regbase + ME8100_COUNTER_REG_2); |
|
1582 |
|
1583 return 0; |
|
1584 } |
|
1585 |
|
1586 |
|
1587 |
|
1588 |
|
1589 /* |
|
1590 * Routine: |
|
1591 * me8100_read_counter_0 |
|
1592 * |
|
1593 * Description: |
|
1594 * This function is called by the me8100_ioctl, in order to read a byte |
|
1595 * from the counter 0 |
|
1596 * |
|
1597 * Parameter list: |
|
1598 * Name Type Access Description |
|
1599 *-------------------------------------------------------------------------- |
|
1600 * *arg unsigned char r Carries the value to user. |
|
1601 * *info me8100_info_type r Global board context. |
|
1602 * |
|
1603 * Result: |
|
1604 * On success the return value is 0, else is failure. |
|
1605 *-------------------------------------------------------------------------- |
|
1606 * Author: GG |
|
1607 * Modification: |
|
1608 */ |
|
1609 static int me8100_read_counter_0(unsigned char *arg, me8100_info_type *info){ |
|
1610 int err = 0; |
|
1611 unsigned char value; |
|
1612 |
|
1613 PDEBUG("me8100_read_counter_0() is executed\n"); |
|
1614 |
|
1615 value = inb(info->me8100_regbase + ME8100_COUNTER_REG_0); |
|
1616 err = copy_to_user(arg, &value, sizeof(value)); |
|
1617 if(err) |
|
1618 return err; |
|
1619 |
|
1620 return 0; |
|
1621 } |
|
1622 |
|
1623 |
|
1624 |
|
1625 |
|
1626 |
|
1627 /* |
|
1628 * Routine: |
|
1629 * me8100_read_counter_1 |
|
1630 * |
|
1631 * Description: |
|
1632 * This function is called by the me8100_ioctl, in order to read a byte |
|
1633 * from the counter 1 |
|
1634 * |
|
1635 * Parameter list: |
|
1636 * Name Type Access Description |
|
1637 *-------------------------------------------------------------------------- |
|
1638 * *arg unsigned char r Carries the value to user. |
|
1639 * *info me8100_info_type r Global board context. |
|
1640 * |
|
1641 * Result: |
|
1642 * On success the return value is 0, else is failure. |
|
1643 *-------------------------------------------------------------------------- |
|
1644 * Author: GG |
|
1645 * Modification: |
|
1646 */ |
|
1647 static int me8100_read_counter_1(unsigned char *arg, me8100_info_type *info){ |
|
1648 int err = 0; |
|
1649 unsigned char value; |
|
1650 |
|
1651 PDEBUG("me8100_read_counter_1() is executed\n"); |
|
1652 |
|
1653 value = inb(info->me8100_regbase + ME8100_COUNTER_REG_1); |
|
1654 err = copy_to_user(arg, &value, sizeof(value)); |
|
1655 if(err) |
|
1656 return err; |
|
1657 |
|
1658 return 0; |
|
1659 } |
|
1660 |
|
1661 |
|
1662 |
|
1663 |
|
1664 |
|
1665 /* |
|
1666 * Routine: |
|
1667 * me8100_read_counter_2 |
|
1668 * |
|
1669 * Description: |
|
1670 * This function is called by the me8100_ioctl, in order to read a byte |
|
1671 * from the counter 2 |
|
1672 * |
|
1673 * Parameter list: |
|
1674 * Name Type Access Description |
|
1675 *-------------------------------------------------------------------------- |
|
1676 * *arg unsigned char r Carries the value to user. |
|
1677 * minor int r specifies the board |
|
1678 * |
|
1679 * Result: |
|
1680 * On success the return value is 0, else is failure. |
|
1681 *-------------------------------------------------------------------------- |
|
1682 * Author: GG |
|
1683 * Modification: |
|
1684 */ |
|
1685 static int me8100_read_counter_2(unsigned char *arg, me8100_info_type *info){ |
|
1686 int err = 0; |
|
1687 unsigned char value; |
|
1688 |
|
1689 PDEBUG("me8100_read_counter_2() is executed\n"); |
|
1690 |
|
1691 value = inb(info->me8100_regbase + ME8100_COUNTER_REG_2); |
|
1692 err = copy_to_user(arg, &value, sizeof(value)); |
|
1693 if(err) |
|
1694 return err; |
|
1695 |
|
1696 return 0; |
|
1697 } |
|
1698 |
|
1699 |
|
1700 |
|
1701 /* |
|
1702 * Routine: |
|
1703 * me8100_setup_counter |
|
1704 * |
|
1705 * Description: |
|
1706 * This function is called by the me8100_ioctl, in order to setup the |
|
1707 * the counter. |
|
1708 * |
|
1709 * Parameter list: |
|
1710 * Name Type Access Description |
|
1711 *-------------------------------------------------------------------------- |
|
1712 * *arg unsigned char r Carries the value from user. |
|
1713 * *info me8100_info_type r Global board context. |
|
1714 * |
|
1715 * Result: |
|
1716 * On success the return value is 0, else is failure. |
|
1717 *-------------------------------------------------------------------------- |
|
1718 * Author: GG |
|
1719 * Modification: |
|
1720 */ |
|
1721 static int me8100_setup_counter(unsigned char *arg, me8100_info_type *info){ |
|
1722 int err = 0; |
|
1723 unsigned char value = 0; |
|
1724 |
|
1725 PDEBUG("me8100_setup_counter() is executed\n"); |
|
1726 |
|
1727 err = copy_from_user(&value, arg, sizeof(value)); |
|
1728 if(err) |
|
1729 return err; |
|
1730 |
|
1731 PDEBUG("me8100_setup_counter_0:ctrl=0x%02X\n", value); |
|
1732 PDEBUG("me8100_setup_counter_0():To offset=0x%02X\n", |
|
1733 ME8100_COUNTER_CTRL_REG); |
|
1734 outb(value, info->me8100_regbase + ME8100_COUNTER_CTRL_REG); |
|
1735 |
|
1736 return 0; |
|
1737 } |
|
1738 |
|
1739 |
|
1740 |
|
1741 /* |
|
1742 * Routine: |
|
1743 * me8100_get_serial |
|
1744 * |
|
1745 * Description: |
|
1746 * This function is called by the me8100_ioctl, in order to get the |
|
1747 * serial number of the board. |
|
1748 * |
|
1749 * Parameter list: |
|
1750 * Name Type Access Description |
|
1751 *-------------------------------------------------------------------------- |
|
1752 * *arg unsigned int w Carries the value to user. |
|
1753 * *info me8100_info_type r Global board context. |
|
1754 * |
|
1755 * Result: |
|
1756 * On success the return value is 0, else is failure. |
|
1757 *-------------------------------------------------------------------------- |
|
1758 * Author: GG |
|
1759 * Modification: |
|
1760 */ |
|
1761 static int me8100_get_serial(unsigned int *arg, me8100_info_type *info){ |
|
1762 int err = 0; |
|
1763 unsigned int value; |
|
1764 |
|
1765 PDEBUG("me8100_get_serial() is executed\n"); |
|
1766 |
|
1767 value = info->serial_no; |
|
1768 err = copy_to_user(arg, &value, sizeof(value)); |
|
1769 if(err) |
|
1770 return err; |
|
1771 |
|
1772 return 0; |
|
1773 } |
|
1774 |
|
1775 |
|
1776 |
|
1777 |
|
1778 /* |
|
1779 * Routine: |
|
1780 * me8100_get_name |
|
1781 * |
|
1782 * Description: |
|
1783 * This function is called by the me8100_ioctl, in order to get the |
|
1784 * name of the board. |
|
1785 * |
|
1786 * Parameter list: |
|
1787 * Name Type Access Description |
|
1788 *-------------------------------------------------------------------------- |
|
1789 * *arg unsigned int w Carries the value to user. |
|
1790 * *info me8100_info_type r Global board context. |
|
1791 * |
|
1792 * Result: |
|
1793 * On success the return value is 0, else is failure. |
|
1794 *-------------------------------------------------------------------------- |
|
1795 * Author: GG |
|
1796 * Modification: |
|
1797 */ |
|
1798 static int me8100_get_name(me8100_version_enum_type *arg, me8100_info_type *info){ |
|
1799 int err = 0; |
|
1800 unsigned int value; |
|
1801 |
|
1802 PDEBUG("me8100_get_name() is executed\n"); |
|
1803 |
|
1804 value = info->version; |
|
1805 err = copy_to_user(arg, &value, sizeof(value)); |
|
1806 if(err) |
|
1807 return err; |
|
1808 |
|
1809 return 0; |
|
1810 } |
|
1811 |
|
1812 |
|
1813 |
|
1814 |
|
1815 /* |
|
1816 * Routine: |
|
1817 * me8100_int_occur |
|
1818 * |
|
1819 * Description: |
|
1820 * This function is called by the me8100_ioctl, in order to find out, |
|
1821 * which interrupt input rised the last interrupt on a me8100 board. |
|
1822 * |
|
1823 * Parameter list: |
|
1824 * Name Type Access Description |
|
1825 *-------------------------------------------------------------------------- |
|
1826 * *arg me8100_int_occur_type w Carries the value to user. |
|
1827 * *info me8100_info_type r Global board context. |
|
1828 * |
|
1829 * Result: |
|
1830 * On success the return value is 0, else is failure. |
|
1831 *-------------------------------------------------------------------------- |
|
1832 * Author: GG |
|
1833 * Modification: |
|
1834 */ |
|
1835 static int me8100_int_occur(me8100_int_occur_type *arg, me8100_info_type *info){ |
|
1836 int err = 0; |
|
1837 unsigned long flags; |
|
1838 me8100_int_occur_type int_occur; |
|
1839 |
|
1840 PDEBUG("me8100_read_int_occur() is executed\n"); |
|
1841 |
|
1842 save_flags(flags); |
|
1843 cli(); |
|
1844 int_occur.int1 = info->int1; |
|
1845 int_occur.int2 = info->int2; |
|
1846 restore_flags(flags); |
|
1847 |
|
1848 err = copy_to_user(arg, &int_occur, sizeof(int_occur)); |
|
1849 if(err) |
|
1850 return err; |
|
1851 return 0; |
|
1852 } |
|
1853 |
|
1854 |
|
1855 |
|
1856 |
|
1857 /* |
|
1858 * Routine: |
|
1859 * me8100_setup_icsr |
|
1860 * |
|
1861 * Description: |
|
1862 * This function is called by the me8100_ioctl, in order to write a value |
|
1863 * to the plx icsr (offset 0x4C) |
|
1864 * |
|
1865 * Parameter list: |
|
1866 * Name Type Access Description |
|
1867 *-------------------------------------------------------------------------- |
|
1868 * *arg unsigned char r Carries the value from user. |
|
1869 * *info me8100_info_type r Global board context. |
|
1870 * |
|
1871 * Result: |
|
1872 * On success the return value is 0, else is failure. |
|
1873 *-------------------------------------------------------------------------- |
|
1874 * Author: GG |
|
1875 * Modification: |
|
1876 */ |
|
1877 static int me8100_setup_icsr(unsigned char *arg, me8100_info_type *info){ |
|
1878 int err = 0; |
|
1879 unsigned char value = 0; |
|
1880 |
|
1881 PDEBUG("me8100_setup_icsr() is executed\n"); |
|
1882 |
|
1883 err = copy_from_user(&value, arg, sizeof(value)); |
|
1884 if(err) |
|
1885 return err; |
|
1886 |
|
1887 PDEBUG("me8100_setup_icsr:icsr=0x%02X\n", value); |
|
1888 PDEBUG("me8100_setup_icsr:To offset=0x%02X\n", |
|
1889 PLX_ICSR); |
|
1890 outb(value, info->plx_regbase + PLX_ICSR); |
|
1891 |
|
1892 return 0; |
|
1893 } |
|
1894 |
|
1895 |
|
1896 |
|
1897 /* |
|
1898 * Routine: |
|
1899 * me8100_read_icsr |
|
1900 * |
|
1901 * Description: |
|
1902 * This function is called by the me8100_ioctl, in order to read the |
|
1903 * the plx icsr (offset 0x4C) |
|
1904 * |
|
1905 * Parameter list: |
|
1906 * Name Type Access Description |
|
1907 *-------------------------------------------------------------------------- |
|
1908 * *arg unsigned char w Carries the value to user. |
|
1909 * *info me8100_info_type r Global board context. |
|
1910 * |
|
1911 * Result: |
|
1912 * On success the return value is 0, else is failure. |
|
1913 *-------------------------------------------------------------------------- |
|
1914 * Author: GG |
|
1915 * Modification: |
|
1916 */ |
|
1917 static int me8100_read_icsr(unsigned char *arg, me8100_info_type *info){ |
|
1918 int err = 0; |
|
1919 unsigned char value; |
|
1920 |
|
1921 PDEBUG("me8100_read_icsr() is executed\n"); |
|
1922 |
|
1923 value = inb(info->plx_regbase + PLX_ICSR); |
|
1924 err = copy_to_user(arg, &value, sizeof(value)); |
|
1925 if(err) |
|
1926 return err; |
|
1927 |
|
1928 return 0; |
|
1929 } |
|
1930 |
|
1931 |
|
1932 |
|
1933 /* |
|
1934 * Routine: |
|
1935 * me8100_get_int_count |
|
1936 * |
|
1937 * Description: |
|
1938 * This function is called by me8100_ioctl, in order to get the count of |
|
1939 * interrupts occoured since the module was loaded. |
|
1940 * |
|
1941 * Parameter list: |
|
1942 * Name Type Access Description |
|
1943 *-------------------------------------------------------------------------- |
|
1944 * *arg int w Carries the value to user. |
|
1945 * *info me8100_info_type r Global board context. |
|
1946 * |
|
1947 * Result: |
|
1948 * On success the return value is 0, else is failure. |
|
1949 *-------------------------------------------------------------------------- |
|
1950 * Author: GG |
|
1951 * Modification: |
|
1952 */ |
|
1953 static int me8100_get_int_count(me8100_int_occur_type *arg, |
|
1954 me8100_info_type *info){ |
|
1955 me8100_int_occur_type int_count; |
|
1956 unsigned long flags; |
|
1957 |
|
1958 PDEBUG("me8100_get_int_count() is executed\n"); |
|
1959 |
|
1960 save_flags(flags); |
|
1961 cli(); |
|
1962 int_count.int1 = info->int_count_1; |
|
1963 int_count.int2 = info->int_count_2; |
|
1964 restore_flags(flags); |
|
1965 |
|
1966 if(copy_to_user(arg, &int_count, sizeof(int_count))) |
|
1967 return -EFAULT; |
|
1968 return 0; |
|
1969 } |
|
1970 |
|
1971 |
|
1972 |
|
1973 |
|
1974 /* |
|
1975 * Routine: |
|
1976 * me8100_isr |
|
1977 * |
|
1978 * Description: |
|
1979 * This is the interrupt service routine of the ME8100 board. This |
|
1980 * function is called, when the interrupt logic of the plx and the board |
|
1981 * is enabled and an extarnal interrupt occures. First it checks if the |
|
1982 * interrupt number is right and if this board rises the interrupt by |
|
1983 * reading the interrupt status register of the PLX. It remarks the input |
|
1984 * (Int1 or Int2) which rises the interrupt in the global |
|
1985 * info_vec. Then it informs the process, probably remarked in |
|
1986 * the fasync structure. |
|
1987 * |
|
1988 * Parameter list: |
|
1989 * Name Type Access Description |
|
1990 *-------------------------------------------------------------------------- |
|
1991 * irq int read number of interrupt occured |
|
1992 * dev_id void* read pointer to board specific |
|
1993 * informations |
|
1994 * regs struct pt_regs * read pointer to cpu register |
|
1995 * |
|
1996 * Result: |
|
1997 *-------------------------------------------------------------------------- |
|
1998 * Author: GG |
|
1999 * Modification: |
|
2000 */ |
|
2001 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){ |
|
2002 unsigned char icsr = 0; |
|
2003 unsigned short dummy = 0; |
|
2004 me8100_info_type *board_context; |
|
2005 struct fasync_struct *fasync_ptr; |
|
2006 |
|
2007 PDEBUG("me8100_isr() is executed\n"); |
|
2008 |
|
2009 board_context = (me8100_info_type *) dev_id; |
|
2010 |
|
2011 fasync_ptr = board_context->file_ptr->private_data; |
|
2012 |
|
2013 if(irq != board_context->int_line){ |
|
2014 PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq); |
|
2015 return; |
|
2016 } |
|
2017 |
|
2018 board_context->int1 = 0; |
|
2019 board_context->int2 = 0; |
|
2020 |
|
2021 icsr = inb(board_context->plx_regbase + PLX_ICSR); |
|
2022 |
|
2023 if((icsr & 0x04)&&(icsr & 0x40)&&(icsr & 0x01)){ |
|
2024 PDEBUG("me8100_isr():Int1 occured\n"); |
|
2025 board_context->int1 = 1; |
|
2026 board_context->int_count_1++; |
|
2027 dummy = inw(board_context->me8100_regbase + ME8100_RES_INT_REG_A); |
|
2028 } |
|
2029 |
|
2030 if((icsr & 0x20)&&(icsr & 0x40)&&(icsr & 0x08)){ |
|
2031 PDEBUG("me8100_isr():Int2 occured\n"); |
|
2032 board_context->int2 = 1; |
|
2033 board_context->int_count_2++; |
|
2034 dummy = inw(board_context->me8100_regbase + ME8100_RES_INT_REG_B); |
|
2035 } |
|
2036 |
|
2037 if(!(board_context->int1 || board_context->int2)){ |
|
2038 PDEBUG("me8100_isr():Not this Board\n"); |
|
2039 return; |
|
2040 } |
|
2041 |
|
2042 if(fasync_ptr){ |
|
2043 PDEBUG("me8100_isr():send signal to process\n"); |
|
2044 kill_fasync(&fasync_ptr, SIGIO, POLL_IN); |
|
2045 } |
|
2046 } |
|
2047 |
|
2048 |
|
2049 |
|
2050 |
|
2051 /* |
|
2052 * Routine: |
|
2053 * cleanup_module |
|
2054 * |
|
2055 * Description: |
|
2056 * This routine is called, when the module is removed from the kernel. |
|
2057 * It unregisters the module on the system. |
|
2058 * |
|
2059 * Parameter list: |
|
2060 * Name Type Access Description |
|
2061 *-------------------------------------------------------------------------- |
|
2062 * |
|
2063 * Result: |
|
2064 *-------------------------------------------------------------------------- |
|
2065 * Author: GG |
|
2066 * Modification: |
|
2067 */ |
|
2068 void cleanup_module(void){ |
|
2069 extern unsigned int major; |
|
2070 int err; |
|
2071 |
|
2072 PDEBUG("cleanup_module() is executed\n"); |
|
2073 |
|
2074 if(major){ |
|
2075 err = unregister_chrdev(major, ME8100_NAME); |
|
2076 if(err) |
|
2077 printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n"); |
|
2078 } |
|
2079 } |