123 |
123 |
124 |
124 |
125 /* Major Device Number. 0 means to get it automatically from the System */ |
125 /* Major Device Number. 0 means to get it automatically from the System */ |
126 static unsigned int major = 0; |
126 static unsigned int major = 0; |
127 |
127 |
|
128 /* The queue all the readers are on. */ |
|
129 DECLARE_WAIT_QUEUE_HEAD(me8100_readq); |
|
130 |
|
131 |
128 |
132 |
129 /* Prototypes */ |
133 /* Prototypes */ |
130 static int me8100_open(struct inode *, struct file *); |
134 static int me8100_open(struct inode *, struct file *); |
131 static int me8100_release(struct inode *, struct file *); |
135 static int me8100_release(struct inode *, struct file *); |
132 static int me8100_ioctl(struct inode *, struct file *, |
136 static int me8100_ioctl(struct inode *, struct file *, |
338 * for compatibility. (GG) |
342 * for compatibility. (GG) |
339 * |
343 * |
340 */ |
344 */ |
341 static int me8100_init_board(me8100_info_type *info, |
345 static int me8100_init_board(me8100_info_type *info, |
342 struct pci_dev *pci_dev_ptr){ |
346 struct pci_dev *pci_dev_ptr){ |
|
347 int i; |
343 int result = 0; |
348 int result = 0; |
344 unsigned int plx_regbase_tmp; |
349 unsigned int plx_regbase_tmp; |
345 unsigned int me8100_regbase_tmp; |
350 unsigned int me8100_regbase_tmp; |
346 unsigned int swap_regbase_tmp; |
351 unsigned int swap_regbase_tmp; |
347 unsigned int regbase_tmp; |
352 unsigned int regbase_tmp; |
435 } |
440 } |
436 info->me8100_regbase_size = ME8100_BASE_SIZE; |
441 info->me8100_regbase_size = ME8100_BASE_SIZE; |
437 info->me8100_regbase = me8100_regbase_tmp & PCI_BASE_ADDRESS_IO_MASK; |
442 info->me8100_regbase = me8100_regbase_tmp & PCI_BASE_ADDRESS_IO_MASK; |
438 PDEBUG("me8100_init_board():IO at 0x%04X\n", info->me8100_regbase); |
443 PDEBUG("me8100_init_board():IO at 0x%04X\n", info->me8100_regbase); |
439 |
444 |
440 info->subinfo[0].regbase = info->me8100_regbase; |
|
441 info->subinfo[1].regbase = info->me8100_regbase + 0x0C; |
|
442 |
|
443 |
|
444 /*--------------------------- init device info ----------------------------*/ |
445 /*--------------------------- init device info ----------------------------*/ |
445 |
446 |
446 result = pci_read_config_dword(pci_dev_ptr, 0x2C, &info->serial_no); |
447 result = pci_read_config_dword(pci_dev_ptr, 0x2C, &info->serial_no); |
447 if(result != PCIBIOS_SUCCESSFUL){ |
448 if(result != PCIBIOS_SUCCESSFUL){ |
448 printk(KERN_ERR"ME8100:me8100_init_board:Can't get serial_no\n"); |
449 printk(KERN_ERR"ME8100:me8100_init_board:Can't get serial_no\n"); |
473 PDEBUG("me8100_init_board():pci_bus_no = 0x%02X\n", info->pci_bus_no); |
474 PDEBUG("me8100_init_board():pci_bus_no = 0x%02X\n", info->pci_bus_no); |
474 |
475 |
475 info->int_line = pci_dev_ptr->irq; |
476 info->int_line = pci_dev_ptr->irq; |
476 PDEBUG("me8100_init_board():int_line = %d\n", info->int_line); |
477 PDEBUG("me8100_init_board():int_line = %d\n", info->int_line); |
477 |
478 |
478 info->int_count_1 = 0; |
|
479 info->int_count_2 = 0; |
|
480 info->int1 = 0; |
|
481 info->int2 = 0; |
|
482 info->file_ptr = NULL; |
479 info->file_ptr = NULL; |
483 info->fasync_ptr = NULL; |
|
484 info->board_in_use = 0; |
480 info->board_in_use = 0; |
|
481 |
|
482 info->subinfo[0].regbase = info->me8100_regbase; |
|
483 info->subinfo[1].regbase = info->me8100_regbase + 0x0C; |
|
484 |
|
485 for (i = 0; i <= 1; ++i) { |
|
486 info->subinfo[i].int_seen = 0; |
|
487 info->subinfo[i].int_count = 0; |
|
488 info->subinfo[i].fasync_ptr = NULL; |
|
489 } |
|
490 |
485 |
491 |
486 /*--------------------------- Reset the board -----------------------------*/ |
492 /*--------------------------- Reset the board -----------------------------*/ |
487 |
493 |
488 result = me8100_reset_board(info); |
494 result = me8100_reset_board(info); |
489 if(result){ |
495 if(result){ |
579 |
585 |
580 device = DEVICE(MINOR(inode_ptr->i_rdev)); |
586 device = DEVICE(MINOR(inode_ptr->i_rdev)); |
581 subdevice = SUBDEVICE(MINOR(inode_ptr->i_rdev)); |
587 subdevice = SUBDEVICE(MINOR(inode_ptr->i_rdev)); |
582 PDEBUG("*** device: %d, subdevice %d\n", device, subdevice); |
588 PDEBUG("*** device: %d, subdevice %d\n", device, subdevice); |
583 |
589 |
584 info = &info_vec[device]; |
590 if(device >= me8100_board_count){ |
585 subinfo = &info->subinfo[subdevice]; |
591 printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", device); |
|
592 return -ENODEV; |
|
593 } |
586 |
594 |
587 /* Currently we can't support the old style minor numbers. */ |
595 /* Currently we can't support the old style minor numbers. */ |
588 if (subdevice < 0) { |
596 if (subdevice < 0) { |
589 printk(KERN_ERR "ME8100:me8100_open(): Bad subdevice %d\n", subdevice); |
597 printk(KERN_ERR "ME8100:me8100_open(): Bad subdevice %d\n", subdevice); |
590 return -ENODEV; |
598 return -ENODEV; |
591 } |
599 } |
592 |
600 |
593 |
601 info = &info_vec[device]; |
594 if(device >= me8100_board_count){ |
602 subinfo = &info->subinfo[subdevice]; |
595 printk(KERN_ERR"ME8100:me8100_open():Board %d doesn't exist\n", device); |
|
596 return -ENODEV; |
|
597 } |
|
598 |
603 |
599 MOD_INC_USE_COUNT; |
604 MOD_INC_USE_COUNT; |
600 |
605 |
601 if (file_ptr->f_mode & FMODE_WRITE) { |
606 if (file_ptr->f_mode & FMODE_WRITE) { |
602 /* If we're the first write, the control register has to be |
607 /* If we're the first writer, the control register has to be |
603 * setup properly. */ |
608 * setup properly. */ |
604 |
609 |
605 PDEBUG("*** open for writing\n"); |
610 PDEBUG("*** open for writing\n"); |
606 |
611 |
607 if (0 == subinfo->num_writer++) { |
612 if (0 == subinfo->num_writer++) { |
608 subinfo->ctrl_reg |= ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE; |
613 PDEBUG("*** first writer\n"); |
609 PDEBUG("*** adding %0x to ctrl: 0x%04x\n", |
614 subinfo->ctrl_wflags = ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE; |
610 ME8100_CTRL_ENIO | ME8100_CTRL_SOURCE, subinfo->ctrl_reg); |
615 subinfo->ctrl_reg |= subinfo->ctrl_wflags; |
|
616 PDEBUG("*** adding 0x%0x to ctrl => 0x%04x\n", |
|
617 subinfo->ctrl_wflags, subinfo->ctrl_reg); |
611 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
618 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
612 } |
619 } |
613 } |
620 } |
614 |
621 |
615 |
622 |
621 |
628 |
622 struct me8100_private_data *priv; |
629 struct me8100_private_data *priv; |
623 |
630 |
624 PDEBUG("*** open for reading\n"); |
631 PDEBUG("*** open for reading\n"); |
625 |
632 |
|
633 /* The first reader should setup the IRQs (enabling IRQ handling |
|
634 * with the full bit mask. It might be modified later. */ |
626 if (0 == subinfo->num_reader++) { |
635 if (0 == subinfo->num_reader++) { |
627 |
636 int mask = 0xffff; |
|
637 unsigned short icsr = PCI_INT_EN |
|
638 | ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice)); |
628 PDEBUG("*** first reader...\n"); |
639 PDEBUG("*** first reader...\n"); |
629 |
640 subinfo->ctrl_rflags = 0; |
630 if (!(priv = kmalloc(sizeof(*priv), GFP_KERNEL))) { |
641 |
|
642 /* Allocate memory for the private data. If allocating fails, |
|
643 * call m8100_release() (which in turn decrements the mod-in-use-count) |
|
644 * and return IO error. */ |
|
645 if (NULL == (priv = kmalloc(sizeof(*priv), GFP_KERNEL))) { |
631 printk(KERN_ERR"ME8100:me8100_open: kmalloc() failed.\n"); |
646 printk(KERN_ERR"ME8100:me8100_open: kmalloc() failed.\n"); |
632 me8100_release(inode_ptr, file_ptr); |
647 me8100_release(inode_ptr, file_ptr); |
633 return -EIO; |
648 return -EIO; |
634 } |
649 } |
635 |
650 |
636 priv->last_read = 0; |
651 priv->last_read = 0; |
637 file_ptr->private_data = priv; |
652 file_ptr->private_data = priv; |
638 |
653 |
639 /* Now we've to setup the IRQ line. We suppose that it should be done |
654 /* 1) setup the PLX register */ |
640 * in "mask" manner. If somebody wishes to do it the otherway or if somebody |
655 PDEBUG("*** plx = 0x%0x\n", icsr); |
641 * wants to change the mask, ioctl() should be used. */ |
656 outb(icsr, info->plx_regbase + PLX_ICSR); |
642 { |
657 |
643 int mask = 0xffff; |
658 /* 2) setup the irq flags in regbase */ |
644 unsigned short icsr = PCI_INT_EN | ((LOCAL_INT_EN | LOCAL_INT_POL) << (3 * subdevice)); |
659 subinfo->ctrl_rflags = ME8100_CTRL_IRQ_MASK; |
645 |
660 subinfo->ctrl_reg |= subinfo->ctrl_rflags; |
646 |
661 PDEBUG("*** adding 0x%0x to ctrl => 0x%04x\n", |
647 /* 1) setup the PLX register */ |
662 subinfo->ctrl_rflags, subinfo->ctrl_reg); |
648 PDEBUG("*** plx = 0x%0x\n", icsr); |
663 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
649 outb(icsr, info->plx_regbase + PLX_ICSR); |
664 |
650 |
665 /* 3) setup the interrupt mask */ |
651 /* 2) setup the irq flags in regbase */ |
666 PDEBUG("*** irqmask = 0x%04x\n", mask); |
652 subinfo->ctrl_reg |= ME8100_CTRL_IRQ_MASK; |
667 outw(mask, subinfo->regbase + ME8100_MASK_REG); |
653 PDEBUG("*** adding %0x to ctrl: 0x%04x\n", ME8100_CTRL_IRQ_MASK, |
668 |
654 subinfo->ctrl_reg); |
|
655 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
|
656 |
|
657 /* 3) setup the interrupt mask */ |
|
658 PDEBUG("*** irqmask = 0x%04x\n", mask); |
|
659 outw(mask, subinfo->regbase + ME8100_MASK_REG); |
|
660 |
|
661 } |
|
662 } /* first reader */ |
669 } /* first reader */ |
663 } /* reader */ |
670 } /* reader */ |
664 |
671 |
665 |
672 |
666 return 0; |
673 return 0; |
709 |
716 |
710 /* Resetting write mode if last writer is gone */ |
717 /* Resetting write mode if last writer is gone */ |
711 if (file_ptr->f_mode & FMODE_WRITE) { |
718 if (file_ptr->f_mode & FMODE_WRITE) { |
712 PDEBUG("*** writer closes\n"); |
719 PDEBUG("*** writer closes\n"); |
713 if (0 == --subinfo->num_writer) { |
720 if (0 == --subinfo->num_writer) { |
714 subinfo->ctrl_reg &= !ME8100_CTRL_ENIO; |
721 /* |
715 PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
722 PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
|
723 subinfo->ctrl_reg &= !subinfo->ctrl_wflags; |
|
724 subinfo->ctrl_wflags = 0; |
716 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
725 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
|
726 */ |
717 } |
727 } |
718 } |
728 } |
719 |
729 |
720 if (file_ptr->f_mode & FMODE_READ) { |
730 if (file_ptr->f_mode & FMODE_READ) { |
721 PDEBUG("*** reader close\n"); |
731 PDEBUG("*** reader close\n"); |
722 if (0 == --subinfo->num_reader) { |
732 if (0 == --subinfo->num_reader) { |
723 PDEBUG("*** last reader...\n"); |
733 PDEBUG("*** last reader...\n"); |
724 subinfo->ctrl_reg &= !ME8100_CTRL_IRQ_MASK; /* 11 */ |
734 subinfo->ctrl_reg &= !subinfo->ctrl_rflags; |
|
735 subinfo->ctrl_rflags = 0; |
725 PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
736 PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
726 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
737 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
727 } |
738 } |
728 } |
739 } |
729 |
740 |
895 * Author: GG |
909 * Author: GG |
896 * Modufication: |
910 * Modufication: |
897 */ |
911 */ |
898 static int me8100_fasync(int fd, struct file *file_ptr, int mode){ |
912 static int me8100_fasync(int fd, struct file *file_ptr, int mode){ |
899 int val; |
913 int val; |
900 int device; |
914 int device, subdevice; |
901 me8100_info_type *info; |
915 me8100_info_type *info; |
|
916 struct me8100_subinfo *subinfo; |
902 |
917 |
903 device = DEVICE(MINOR(file_ptr->f_dentry->d_inode->i_rdev)); |
918 device = DEVICE(MINOR(file_ptr->f_dentry->d_inode->i_rdev)); |
|
919 subdevice = SUBDEVICE(MINOR(file_ptr->f_dentry->d_inode->i_rdev)); |
904 info = &info_vec[device]; |
920 info = &info_vec[device]; |
|
921 subinfo = &info_vec[device].subinfo[subdevice]; |
905 |
922 |
906 PDEBUG("me8100_fasync() is executed\n"); |
923 PDEBUG("me8100_fasync() is executed\n"); |
907 PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr); |
924 PDEBUG("** fasync_ptr: %p\n", subinfo->fasync_ptr); |
908 val = fasync_helper(fd, file_ptr, mode, &info->fasync_ptr); |
925 val = fasync_helper(fd, file_ptr, mode, &subinfo->fasync_ptr); |
909 PDEBUG("** fasync_ptr: %p\n", info->fasync_ptr); |
926 PDEBUG("** fasync_ptr: %p\n", subinfo->fasync_ptr); |
910 return val; |
927 return val; |
911 } |
928 } |
912 |
929 |
913 |
930 |
914 |
931 |
2091 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){ |
2108 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){ |
2092 unsigned char icsr; |
2109 unsigned char icsr; |
2093 unsigned short dummy; |
2110 unsigned short dummy; |
2094 me8100_info_type *info; |
2111 me8100_info_type *info; |
2095 |
2112 |
2096 PDEBUG("*** => me8100_isr() is executed\n"); |
2113 PDEBUG("=====> me8100_isr() is executed\n"); |
2097 |
2114 |
2098 info = (me8100_info_type *) dev_id; |
2115 info = (me8100_info_type *) dev_id; |
2099 |
2116 |
2100 if(irq != info->int_line){ |
2117 if(irq != info->int_line){ |
2101 PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq); |
2118 PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq); |
2102 return; |
2119 return; |
2103 } |
2120 } |
2104 |
2121 |
2105 info->int1 = 0; |
2122 info->subinfo[0].int_seen = 0; |
2106 info->int2 = 0; |
2123 info->subinfo[1].int_seen = 0; |
2107 |
2124 |
2108 icsr = inb(info->plx_regbase + PLX_ICSR); |
2125 icsr = inb(info->plx_regbase + PLX_ICSR); |
2109 |
2126 PDEBUG("== ICSR: 0x%04x\n", icsr); |
2110 if((icsr & 0x04)&&(icsr & 0x40)&&(icsr & 0x01)){ |
2127 |
|
2128 |
|
2129 /* A: 0x04 & 0x40 & 0x01 */ |
|
2130 /* B: 0x20 & 0x40 & 0x08 */ |
|
2131 if((icsr & 0x45) == 0x45) { |
|
2132 struct me8100_subinfo *subinfo = &info->subinfo[0]; |
2111 PDEBUG("me8100_isr():Int1 occured\n"); |
2133 PDEBUG("me8100_isr():Int1 occured\n"); |
2112 info->int1 = 1; |
2134 subinfo->int_seen = 1; |
2113 info->int_count_1++; |
2135 subinfo->int_count++; |
2114 dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); |
2136 dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); |
2115 } |
2137 if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN); |
2116 |
2138 |
2117 if((icsr & 0x20)&&(icsr & 0x40)&&(icsr & 0x08)){ |
2139 } else if((icsr & 0x68) == 0x68) { |
|
2140 struct me8100_subinfo *subinfo = &info->subinfo[1]; |
2118 PDEBUG("me8100_isr():Int2 occured\n"); |
2141 PDEBUG("me8100_isr():Int2 occured\n"); |
2119 info->int2 = 1; |
2142 subinfo->int_seen = 1; |
2120 info->int_count_2++; |
2143 subinfo->int_count++; |
2121 dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); |
2144 dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); |
2122 } |
2145 if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN); |
2123 |
2146 |
2124 if(!(info->int1 || info->int2)){ |
2147 } else { |
2125 PDEBUG("me8100_isr():Not this Board\n"); |
2148 PDEBUG("me8100_isr():Not this Board\n"); |
2126 return; |
2149 return; |
2127 } |
2150 } |
2128 |
2151 |
2129 if(info->fasync_ptr){ |
2152 PDEBUG("*** wake up sleeper\n"); |
2130 PDEBUG("*** me8100_isr():send signal to process %p->%d\n", |
2153 /* should be splitted too (one queue for each channel) */ |
2131 info->fasync_ptr, info->fasync_ptr->fa_file->f_owner.pid); |
2154 wake_up_interruptible(&me8100_readq); |
2132 kill_fasync(&info->fasync_ptr, SIGIO, POLL_IN); |
|
2133 } |
|
2134 } |
2155 } |
2135 |
2156 |
2136 |
2157 |
2137 |
2158 |
2138 |
2159 |
2195 minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev); |
2216 minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev); |
2196 subinfo = &info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)]; |
2217 subinfo = &info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)]; |
2197 |
2218 |
2198 if (len == 0) return 0; /* do we really need this check? */ |
2219 if (len == 0) return 0; /* do we really need this check? */ |
2199 if (len < 0) return -EINVAL; /* do we really need this check? */ |
2220 if (len < 0) return -EINVAL; /* do we really need this check? */ |
2200 if (priv->last_read >= subinfo->last_change) return 0; /* nothing has changed */ |
2221 if (priv->last_read > subinfo->last_change) { |
|
2222 PDEBUG("*** going to sleep\n"); |
|
2223 interruptible_sleep_on(&me8100_readq); |
|
2224 } |
|
2225 priv->last_read = jiffies; |
2201 |
2226 |
2202 val = inw(subinfo->regbase + ME8100_DI_REG); |
2227 val = inw(subinfo->regbase + ME8100_DI_REG); |
2203 PDEBUG("me8100_read: val=0x%04x\n", val); |
2228 PDEBUG("me8100_read: val=0x%04x\n", val); |
2204 |
2229 |
2205 if (len >= sizeof(val)) { |
2230 if (len >= sizeof(val)) { |