132 static int me8100_ioctl(struct inode *, struct file *, |
132 static int me8100_ioctl(struct inode *, struct file *, |
133 unsigned int , unsigned long ); |
133 unsigned int , unsigned long ); |
134 static int me8100_fasync(int, struct file *, int); |
134 static int me8100_fasync(int, struct file *, int); |
135 static void me8100_isr(int, void *, struct pt_regs *); |
135 static void me8100_isr(int, void *, struct pt_regs *); |
136 static ssize_t me8100_read(struct file *, char *, size_t, loff_t *); |
136 static ssize_t me8100_read(struct file *, char *, size_t, loff_t *); |
|
137 static ssize_t me8100_write(struct file *, const char *, size_t, loff_t *); |
137 |
138 |
138 static int me8100_init_board(me8100_info_type *, struct pci_dev *); |
139 static int me8100_init_board(me8100_info_type *, struct pci_dev *); |
139 static int me8100_reset_board(me8100_info_type *); |
140 static int me8100_reset_board(me8100_info_type *); |
140 |
141 |
141 static int me8100_read_id_a(unsigned short *, me8100_info_type *); |
142 static int me8100_read_id_a(unsigned short *, me8100_info_type *); |
170 static int me8100_setup_icsr(unsigned char *, me8100_info_type *); |
171 static int me8100_setup_icsr(unsigned char *, me8100_info_type *); |
171 static int me8100_read_icsr(unsigned char *, me8100_info_type *); |
172 static int me8100_read_icsr(unsigned char *, me8100_info_type *); |
172 static int me8100_get_board_info(me8100_info_type *, me8100_info_type *); |
173 static int me8100_get_board_info(me8100_info_type *, me8100_info_type *); |
173 static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_type *); |
174 static int me8100_get_int_count(me8100_int_occur_type *, me8100_info_type *); |
174 |
175 |
175 static inline int DEVICE(int i) { return MINOR(i) & 0x0f; } |
176 static inline int DEVICE(int i) { return i & 0x0f; } |
176 static inline int SUBDEVICE(int i) { return MINOR(i) >> 4; } |
177 static inline int SUBDEVICE(int i) { return i >> 4; } |
177 |
178 |
178 |
179 |
179 /* File operations provided by the driver */ |
180 /* File operations provided by the driver */ |
180 static struct file_operations me8100_file_operations = { |
181 static struct file_operations me8100_file_operations = { |
181 #ifdef LINUX_24 |
182 #ifdef LINUX_24 |
182 owner: THIS_MODULE, /* owner */ |
183 owner: THIS_MODULE, /* owner */ |
183 #endif |
184 #endif |
184 llseek: NULL, /* lseek() */ |
185 llseek: NULL, /* lseek() */ |
185 read: me8100_read, /* read() */ |
186 read: me8100_read, /* read() */ |
186 write: NULL, /* write() */ |
187 write: me8100_write, /* write() */ |
187 readdir: NULL, /* readdir() */ |
188 readdir: NULL, /* readdir() */ |
188 poll: NULL, /* poll() */ |
189 poll: NULL, /* poll() */ |
189 ioctl: me8100_ioctl, /* ioctl() */ |
190 ioctl: me8100_ioctl, /* ioctl() */ |
190 mmap: NULL, /* mmap() */ |
191 mmap: NULL, /* mmap() */ |
191 open: me8100_open, /* open() */ |
192 open: me8100_open, /* open() */ |
570 * Modification: |
574 * Modification: |
571 * 01.10.04 Guard board_in_use with spin_lock, cause of race condition |
575 * 01.10.04 Guard board_in_use with spin_lock, cause of race condition |
572 * when compiling for SMP. |
576 * when compiling for SMP. |
573 */ |
577 */ |
574 static int me8100_open(struct inode *inode_ptr, struct file *file_ptr){ |
578 static int me8100_open(struct inode *inode_ptr, struct file *file_ptr){ |
575 int minor = 0; |
579 int device,subdevice; |
576 me8100_info_type *info; |
580 me8100_info_type *info; |
577 |
581 struct me8100_subinfo *subinfo; |
578 PDEBUG("*** me8100_open() is executed for pid: %d\n", file_ptr->f_owner.pid); |
582 |
579 |
583 PDEBUG("*** me8100_open() is executed\n"); |
580 minor = DEVICE(inode_ptr->i_rdev); |
584 |
581 |
585 device = DEVICE(MINOR(inode_ptr->i_rdev)); |
582 PDEBUG("*** device: %d, subdevice %d\n", DEVICE(inode_ptr->i_rdev), |
586 subdevice = SUBDEVICE(MINOR(inode_ptr->i_rdev)); |
583 SUBDEVICE(inode_ptr->i_rdev)); |
587 info = &info_vec[device]; |
584 |
588 subinfo = &info->subinfo[subdevice]; |
585 if(minor >= me8100_board_count){ |
589 |
586 printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", minor); |
590 PDEBUG("*** device: %d, subdevice %d\n", device, subdevice); |
|
591 |
|
592 if(device >= me8100_board_count){ |
|
593 printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", device); |
587 return -ENODEV; |
594 return -ENODEV; |
588 } |
595 } |
589 info = &info_vec[minor]; |
|
590 |
596 |
591 spin_lock(&info->use_lock); |
597 spin_lock(&info->use_lock); |
592 if(info->board_in_use){ |
598 if(info->board_in_use){ |
593 printk(KERN_ERR "WARNING: ME8100:me8100_open():Board %d already in use\n", minor); |
599 printk(KERN_ERR "WARNING: ME8100:me8100_open():Board %d already in use\n", device); |
594 } |
600 } |
595 ++info->board_in_use; |
601 ++info->board_in_use; |
596 spin_unlock(&info->use_lock); |
602 spin_unlock(&info->use_lock); |
597 |
603 |
598 /* info->file_ptr = file_ptr; */ /* müssen wir uns nicht hier merken! */ |
604 if (file_ptr->f_mode & FMODE_WRITE) { |
|
605 PDEBUG("*** open for writing\n"); |
|
606 |
|
607 if (0 == subinfo->num_writer++) { |
|
608 subinfo->ctrl_reg |= ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE; |
|
609 PDEBUG("*** setting ENIO+SOURCE mode: ctrl: 0x%x\n", subinfo->ctrl_reg); |
|
610 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
|
611 } |
|
612 } |
599 |
613 |
600 MOD_INC_USE_COUNT; |
614 MOD_INC_USE_COUNT; |
601 |
615 |
602 return 0; |
616 return 0; |
603 } |
617 } |
709 return -EINVAL; |
736 return -EINVAL; |
710 } |
737 } |
711 |
738 |
712 switch(service){ |
739 switch(service){ |
713 case ME8100_READ_ID_A: |
740 case ME8100_READ_ID_A: |
714 return me8100_read_id_a((unsigned short *) arg, &info_vec[minor]); |
741 return me8100_read_id_a((unsigned short *) arg, &info_vec[device]); |
715 case ME8100_WRITE_CTRL_A: |
742 case ME8100_WRITE_CTRL_A: |
716 return me8100_write_ctrl_a((unsigned short *) arg, &info_vec[minor]); |
743 return me8100_write_ctrl_a((unsigned short *) arg, &info_vec[device]); |
717 case ME8100_RES_INT_A: |
744 case ME8100_RES_INT_A: |
718 return me8100_res_int_a(&info_vec[minor]); |
745 return me8100_res_int_a(&info_vec[device]); |
719 case ME8100_READ_DI_A: |
746 case ME8100_READ_DI_A: |
720 return me8100_read_di_a((unsigned short *) arg, &info_vec[minor]); |
747 return me8100_read_di_a((unsigned short *) arg, &info_vec[device]); |
721 case ME8100_WRITE_DO_A: |
748 case ME8100_WRITE_DO_A: |
722 return me8100_write_do_a((unsigned short *) arg, &info_vec[minor]); |
749 return me8100_write_do_a((unsigned short *) arg, &info_vec[device]); |
723 case ME8100_WRITE_PATTERN_A: |
750 case ME8100_WRITE_PATTERN_A: |
724 return me8100_write_pattern_a((unsigned short *) arg, &info_vec[minor]); |
751 return me8100_write_pattern_a((unsigned short *) arg, &info_vec[device]); |
725 case ME8100_WRITE_MASK_A: |
752 case ME8100_WRITE_MASK_A: |
726 return me8100_write_mask_a((unsigned short *) arg, &info_vec[minor]); |
753 return me8100_write_mask_a((unsigned short *) arg, &info_vec[device]); |
727 case ME8100_READ_INT_DI_A: |
754 case ME8100_READ_INT_DI_A: |
728 return me8100_read_int_di_a((unsigned short *) arg, &info_vec[minor]); |
755 return me8100_read_int_di_a((unsigned short *) arg, &info_vec[device]); |
729 case ME8100_READ_ID_B: |
756 case ME8100_READ_ID_B: |
730 return me8100_read_id_b((unsigned short *) arg, &info_vec[minor]); |
757 return me8100_read_id_b((unsigned short *) arg, &info_vec[device]); |
731 case ME8100_WRITE_CTRL_B: |
758 case ME8100_WRITE_CTRL_B: |
732 return me8100_write_ctrl_b((unsigned short *) arg, &info_vec[minor]); |
759 return me8100_write_ctrl_b((unsigned short *) arg, &info_vec[device]); |
733 case ME8100_RES_INT_B: |
760 case ME8100_RES_INT_B: |
734 return me8100_res_int_b(&info_vec[minor]); |
761 return me8100_res_int_b(&info_vec[device]); |
735 case ME8100_READ_DI_B: |
762 case ME8100_READ_DI_B: |
736 return me8100_read_di_b((unsigned short *) arg, &info_vec[minor]); |
763 return me8100_read_di_b((unsigned short *) arg, &info_vec[device]); |
737 case ME8100_WRITE_DO_B: |
764 case ME8100_WRITE_DO_B: |
738 return me8100_write_do_b((unsigned short *) arg, &info_vec[minor]); |
765 return me8100_write_do_b((unsigned short *) arg, &info_vec[device]); |
739 case ME8100_WRITE_PATTERN_B: |
766 case ME8100_WRITE_PATTERN_B: |
740 return me8100_write_pattern_b((unsigned short *) arg, &info_vec[minor]); |
767 return me8100_write_pattern_b((unsigned short *) arg, &info_vec[device]); |
741 case ME8100_WRITE_MASK_B: |
768 case ME8100_WRITE_MASK_B: |
742 return me8100_write_mask_b((unsigned short *) arg, &info_vec[minor]); |
769 return me8100_write_mask_b((unsigned short *) arg, &info_vec[device]); |
743 case ME8100_READ_INT_DI_B: |
770 case ME8100_READ_INT_DI_B: |
744 return me8100_read_int_di_b((unsigned short *) arg, &info_vec[minor]); |
771 return me8100_read_int_di_b((unsigned short *) arg, &info_vec[device]); |
745 case ME8100_WRITE_COUNTER_0: |
772 case ME8100_WRITE_COUNTER_0: |
746 return me8100_write_counter_0((unsigned char *) arg, &info_vec[minor]); |
773 return me8100_write_counter_0((unsigned char *) arg, &info_vec[device]); |
747 case ME8100_WRITE_COUNTER_1: |
774 case ME8100_WRITE_COUNTER_1: |
748 return me8100_write_counter_1((unsigned char *) arg, &info_vec[minor]); |
775 return me8100_write_counter_1((unsigned char *) arg, &info_vec[device]); |
749 case ME8100_WRITE_COUNTER_2: |
776 case ME8100_WRITE_COUNTER_2: |
750 return me8100_write_counter_2((unsigned char *) arg, &info_vec[minor]); |
777 return me8100_write_counter_2((unsigned char *) arg, &info_vec[device]); |
751 case ME8100_READ_COUNTER_0: |
778 case ME8100_READ_COUNTER_0: |
752 return me8100_read_counter_0((unsigned char *) arg, &info_vec[minor]); |
779 return me8100_read_counter_0((unsigned char *) arg, &info_vec[device]); |
753 case ME8100_READ_COUNTER_1: |
780 case ME8100_READ_COUNTER_1: |
754 return me8100_read_counter_1((unsigned char *) arg, &info_vec[minor]); |
781 return me8100_read_counter_1((unsigned char *) arg, &info_vec[device]); |
755 case ME8100_READ_COUNTER_2: |
782 case ME8100_READ_COUNTER_2: |
756 return me8100_read_counter_2((unsigned char *) arg, &info_vec[minor]); |
783 return me8100_read_counter_2((unsigned char *) arg, &info_vec[device]); |
757 case ME8100_SETUP_COUNTER: |
784 case ME8100_SETUP_COUNTER: |
758 return me8100_setup_counter((unsigned char *) arg, &info_vec[minor]); |
785 return me8100_setup_counter((unsigned char *) arg, &info_vec[device]); |
759 case ME8100_GET_SERIAL: |
786 case ME8100_GET_SERIAL: |
760 return me8100_get_serial((unsigned int *) arg, &info_vec[minor]); |
787 return me8100_get_serial((unsigned int *) arg, &info_vec[device]); |
761 case ME8100_GET_NAME: |
788 case ME8100_GET_NAME: |
762 return me8100_get_name((me8100_version_enum_type *) arg, &info_vec[minor]); |
789 return me8100_get_name((me8100_version_enum_type *) arg, &info_vec[device]); |
763 case ME8100_INT_OCCUR: |
790 case ME8100_INT_OCCUR: |
764 return me8100_int_occur((me8100_int_occur_type *) arg, &info_vec[minor]); |
791 return me8100_int_occur((me8100_int_occur_type *) arg, &info_vec[device]); |
765 case ME8100_SETUP_ICSR: |
792 case ME8100_SETUP_ICSR: |
766 return me8100_setup_icsr((unsigned char *) arg, &info_vec[minor]); |
793 return me8100_setup_icsr((unsigned char *) arg, &info_vec[device]); |
767 case ME8100_READ_ICSR: |
794 case ME8100_READ_ICSR: |
768 return me8100_read_icsr((unsigned char *) arg, &info_vec[minor]); |
795 return me8100_read_icsr((unsigned char *) arg, &info_vec[device]); |
769 case ME8100_GET_BOARD_INFO: |
796 case ME8100_GET_BOARD_INFO: |
770 return me8100_get_board_info((me8100_info_type *)arg, &info_vec[minor]); |
797 return me8100_get_board_info((me8100_info_type *)arg, &info_vec[device]); |
771 case ME8100_GET_INT_COUNT: |
798 case ME8100_GET_INT_COUNT: |
772 return me8100_get_int_count((me8100_int_occur_type *)arg,&info_vec[minor]); |
799 return me8100_get_int_count((me8100_int_occur_type *)arg,&info_vec[device]); |
773 default: |
800 default: |
774 return -EINVAL; |
801 return -EINVAL; |
775 } |
802 } |
776 |
803 |
777 return 0; |
804 return 0; |
2065 * Author: GG |
2090 * Author: GG |
2066 * Modification: |
2091 * Modification: |
2067 */ |
2092 */ |
2068 void cleanup_module(void){ |
2093 void cleanup_module(void){ |
2069 extern unsigned int major; |
2094 extern unsigned int major; |
2070 int minor; |
2095 int device; |
2071 int err; |
2096 int err; |
2072 |
2097 |
2073 |
2098 |
2074 PDEBUG("cleanup_module() is executed\n"); |
2099 PDEBUG("cleanup_module() is executed\n"); |
2075 |
2100 |
2076 for (minor = me8100_board_count - 1; minor > -1; --minor) { |
2101 for (device = me8100_board_count - 1; device > -1; --device) { |
2077 free_irq(info_vec[minor].int_line, (void *) &info_vec[minor]); |
2102 free_irq(info_vec[device].int_line, (void *) &info_vec[device]); |
2078 } |
2103 } |
2079 |
2104 |
2080 if(major){ |
2105 if(major){ |
2081 err = unregister_chrdev(major, ME8100_NAME); |
2106 err = unregister_chrdev(major, ME8100_NAME); |
2082 if(err) |
2107 if(err) |
2083 printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n"); |
2108 printk(KERN_WARNING"ME8100:cleanup_module():cannot unregister major\n"); |
2084 } |
2109 } |
2085 } |
2110 } |
2086 |
2111 |
2087 ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) { |
2112 ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) |
2088 PDEBUG("me8100_read() called\n"); |
2113 { |
|
2114 PDEBUG("me8100_read(%d) called\n", len); |
2089 return -EINVAL; |
2115 return -EINVAL; |
|
2116 } |
|
2117 |
|
2118 /* Writing: we do only write one word (an unsigned short) and return immediatly. Yes, |
|
2119 * we could loop over the complete buffer, but it's not expected to get more data |
|
2120 * than one word. If there's more output, the responsibility is transferred back |
|
2121 * to the C library(?). |
|
2122 */ |
|
2123 ssize_t me8100_write(struct file * file_ptr, const char *buffer, size_t len, loff_t *offset) |
|
2124 { |
|
2125 int err; |
|
2126 unsigned short val; |
|
2127 int minor; |
|
2128 |
|
2129 minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev); |
|
2130 PDEBUG("me8100_write(%d) called\n", len); |
|
2131 |
|
2132 if (len == 0) return 0; /* do we need this? */ |
|
2133 if (len < 0) return -EINVAL; /* do we need this? */ |
|
2134 |
|
2135 /* Take care of "short" writes! */ |
|
2136 if (len >= sizeof(unsigned short)) { |
|
2137 err = get_user(val, (unsigned short*) buffer); |
|
2138 len = sizeof(unsigned short); |
|
2139 } else { |
|
2140 err = get_user(val, (char*) buffer); |
|
2141 val &= 0xff; |
|
2142 } |
|
2143 |
|
2144 if (err) return err; |
|
2145 |
|
2146 PDEBUG("*** me8100_write: val=0x%04x\n", val); |
|
2147 outw(val, info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)].regbase + ME8100_DO_REG); |
|
2148 |
|
2149 return len; |
2090 } |
2150 } |
2091 |
2151 |
2092 /* |
2152 /* |
2093 vim:sts=2 sw=2 aw ai sm: |
2153 vim:sts=2 sw=2 aw ai sm: |
2094 */ |
2154 */ |