476 |
476 |
477 info->subinfo[0].regbase = info->me8100_regbase; |
477 info->subinfo[0].regbase = info->me8100_regbase; |
478 info->subinfo[1].regbase = info->me8100_regbase + 0x0C; |
478 info->subinfo[1].regbase = info->me8100_regbase + 0x0C; |
479 |
479 |
480 for (i = 0; i <= 1; ++i) { |
480 for (i = 0; i <= 1; ++i) { |
481 info->subinfo[i].int_seen = 0; |
481 info->subinfo[i].int_seen = jiffies; /* suppose we got just the first irq */ |
482 info->subinfo[i].int_count = 0; |
482 info->subinfo[i].int_count = 0; |
483 info->subinfo[i].fasync_ptr = NULL; |
483 info->subinfo[i].fasync_ptr = NULL; |
484 init_waitqueue_head(&info->subinfo[i].readq); |
484 init_waitqueue_head(&info->subinfo[i].readq); |
485 } |
485 } |
486 |
486 |
717 PDEBUG("*** writer closes\n"); |
717 PDEBUG("*** writer closes\n"); |
718 if (0 == --subinfo->num_writer) { |
718 if (0 == --subinfo->num_writer) { |
719 PDEBUG("*** last writer...\n"); |
719 PDEBUG("*** last writer...\n"); |
720 /* |
720 /* |
721 PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
721 PDEBUG("*** resetting ENIO mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
722 subinfo->ctrl_reg &= !subinfo->ctrl_wflags; |
722 subinfo->ctrl_reg &= ~subinfo->ctrl_wflags; |
723 subinfo->ctrl_wflags = 0; |
723 subinfo->ctrl_wflags = 0; |
724 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
724 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
725 */ |
725 */ |
726 } |
726 } |
727 } |
727 } |
728 |
728 |
729 if (file_ptr->f_mode & FMODE_READ) { |
729 if (file_ptr->f_mode & FMODE_READ) { |
730 PDEBUG("*** reader close\n"); |
730 PDEBUG("*** reader close\n"); |
731 if (0 == --subinfo->num_reader) { |
731 if (0 == --subinfo->num_reader) { |
732 PDEBUG("*** last reader...\n"); |
732 PDEBUG("*** last reader...\n"); |
733 subinfo->ctrl_reg &= !subinfo->ctrl_rflags; |
733 subinfo->ctrl_reg &= ~subinfo->ctrl_rflags; |
734 subinfo->ctrl_rflags = 0; |
734 subinfo->ctrl_rflags = 0; |
735 PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
735 PDEBUG("*** resetting IRQ mode ctrl: 0x%x\n", subinfo->ctrl_reg); |
736 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
736 outw(subinfo->ctrl_reg, subinfo->regbase + ME8100_CTRL_REG); |
737 } |
737 } |
738 } |
738 } |
2103 *-------------------------------------------------------------------------- |
2103 *-------------------------------------------------------------------------- |
2104 * Author: GG |
2104 * Author: GG |
2105 * Modification: |
2105 * Modification: |
2106 */ |
2106 */ |
2107 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){ |
2107 static void me8100_isr(int irq, void *dev_id, struct pt_regs *regs){ |
|
2108 int i; |
2108 unsigned char icsr; |
2109 unsigned char icsr; |
2109 unsigned short dummy; |
|
2110 me8100_info_type *info; |
2110 me8100_info_type *info; |
2111 //unsigned short icsr_mask[] = { 0x45, 0x68 }; |
2111 |
2112 |
2112 /* A: 0x04 & 0x40 & 0x01 */ |
|
2113 /* B: 0x20 & 0x40 & 0x08 */ |
|
2114 unsigned short icsr_mask[] = { 0x45, 0x68 }; |
|
2115 |
|
2116 info = (me8100_info_type *) dev_id; |
2113 |
2117 |
2114 PDEBUG("=====> me8100_isr() is executed\n"); |
2118 PDEBUG("=====> me8100_isr() is executed\n"); |
2115 |
2119 |
2116 info = (me8100_info_type *) dev_id; |
|
2117 |
2120 |
2118 if(irq != info->int_line){ |
2121 if(irq != info->int_line){ |
2119 PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq); |
2122 PDEBUG("me8100_isr():incorrect interrupt num: %d\n", irq); |
2120 return; |
2123 return; |
2121 } |
2124 } |
2122 |
2125 |
2123 info->subinfo[0].int_seen = 0; |
|
2124 info->subinfo[1].int_seen = 0; |
|
2125 |
2126 |
2126 icsr = inb(info->plx_regbase + PLX_ICSR); |
2127 icsr = inb(info->plx_regbase + PLX_ICSR); |
2127 PDEBUG("== ICSR: 0x%04x\n", icsr); |
2128 PDEBUG("== ICSR: 0x%04x\n", icsr); |
2128 |
2129 |
2129 |
2130 /* We got an interrupt. Now try each possible subdevice in turn. |
2130 /* A: 0x04 & 0x40 & 0x01 */ |
2131 * (There is the possibility that all subdevices raised an intterupt |
2131 /* B: 0x20 & 0x40 & 0x08 */ |
2132 * at the same time. I don't know how this is resolved by the board. |
2132 if((icsr & 0x45) == 0x45) { |
2133 * So we've to try each subdevice in turn.) */ |
2133 struct me8100_subinfo *subinfo = &info->subinfo[0]; |
2134 for (i = 0; i <= 1; ++i) { |
2134 PDEBUG("me8100_isr():Int1 occured\n"); |
2135 if ((icsr & icsr_mask[i]) == icsr_mask[i]) { |
2135 subinfo->int_seen = 1; |
2136 |
2136 subinfo->int_count++; |
2137 struct me8100_subinfo *subinfo = &info->subinfo[i]; |
2137 dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_A); |
2138 subinfo->int_seen = jiffies; |
2138 wake_up_interruptible(&subinfo->readq); |
2139 ++subinfo->int_count; |
2139 if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN); |
2140 |
2140 |
2141 subinfo->int_di = inw(subinfo->regbase + ME8100_INT_DI_REG); |
2141 } else if((icsr & 0x68) == 0x68) { |
2142 inw(subinfo->regbase + ME8100_RES_INT_REG); // dummy read |
2142 struct me8100_subinfo *subinfo = &info->subinfo[1]; |
2143 |
2143 PDEBUG("me8100_isr():Int2 occured\n"); |
2144 PDEBUG("===> read: 0x%04x\n", subinfo->int_di); |
2144 subinfo->int_seen = 1; |
2145 wake_up_interruptible(&subinfo->readq); |
2145 subinfo->int_count++; |
2146 if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN); |
2146 dummy = inw(info->me8100_regbase + ME8100_RES_INT_REG_B); |
2147 } |
2147 wake_up_interruptible(&subinfo->readq); |
2148 } |
2148 if (subinfo->fasync_ptr) kill_fasync(&subinfo->fasync_ptr, SIGIO, POLL_IN); |
2149 |
2149 |
|
2150 } else { |
|
2151 PDEBUG("me8100_isr():Not this Board\n"); |
|
2152 return; |
|
2153 } |
|
2154 |
2150 |
2155 return; |
2151 return; |
2156 |
2152 |
2157 } |
2153 } |
2158 |
2154 |
2200 * This seems to be ok, since it's not expected to read more than one word at once |
2196 * This seems to be ok, since it's not expected to read more than one word at once |
2201 * (the port is one word wide only!) |
2197 * (the port is one word wide only!) |
2202 * |
2198 * |
2203 * If a a reader (identified by the file_ptr) calls this functions the first time, |
2199 * If a a reader (identified by the file_ptr) calls this functions the first time, |
2204 * the current input is returned. Every succsessive read is then put to sleep until |
2200 * the current input is returned. Every succsessive read is then put to sleep until |
2205 * the status of the input changed. (Unless the IRQ behaviour if the device is changed by |
2201 * the status of the input changed. (Signalled by an interrupt.) If awoken from |
2206 * some ioctl()s.) |
2202 * interrupt, the value that caused the interrupt ist read. |
2207 */ |
2203 */ |
2208 ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) |
2204 ssize_t me8100_read(struct file * file_ptr, char *buffer, size_t len, loff_t *offset) |
2209 { |
2205 { |
2210 int err; |
2206 int err; |
2211 unsigned short val; |
2207 unsigned short val; |
2218 minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev); |
2214 minor = MINOR(file_ptr->f_dentry->d_inode->i_rdev); |
2219 subinfo = &info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)]; |
2215 subinfo = &info_vec[DEVICE(minor)].subinfo[SUBDEVICE(minor)]; |
2220 |
2216 |
2221 if (len == 0) return 0; /* do we really need this check? */ |
2217 if (len == 0) return 0; /* do we really need this check? */ |
2222 if (len < 0) return -EINVAL; /* do we really need this check? */ |
2218 if (len < 0) return -EINVAL; /* do we really need this check? */ |
2223 if (priv->last_read > subinfo->last_change) { |
2219 |
|
2220 if (priv->last_read >= subinfo->int_seen) { /* alread seen, sleep */ |
2224 PDEBUG("*** going to sleep\n"); |
2221 PDEBUG("*** going to sleep\n"); |
2225 interruptible_sleep_on(&subinfo->readq); |
2222 if (wait_event_interruptible(subinfo->readq, (priv->last_read != subinfo->int_seen))) { |
2226 } |
2223 PDEBUG("** awoken on signal?\n"); |
2227 priv->last_read = jiffies; |
2224 return -ERESTARTSYS; |
2228 |
2225 } |
2229 val = inw(subinfo->regbase + ME8100_DI_REG); |
2226 val = subinfo->int_di; /* the value that caused the interrupt */ |
2230 PDEBUG("me8100_read: val=0x%04x\n", val); |
2227 } else { /* not yet seen ... */ |
|
2228 val = inw(subinfo->regbase + ME8100_DI_REG); |
|
2229 PDEBUG("me8100_read: val=0x%04x\n", val); |
|
2230 } |
|
2231 |
|
2232 priv->last_read = subinfo->int_seen; |
2231 |
2233 |
2232 if (len >= sizeof(val)) { |
2234 if (len >= sizeof(val)) { |
2233 err = put_user(val, (unsigned short*) buffer); |
2235 err = put_user(val, (unsigned short*) buffer); |
2234 len = sizeof(val); |
2236 len = sizeof(val); |
2235 } else { |
2237 } else { |