patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / m68k / sun3 / sun3ints.c
1  /*
2  * linux/arch/m68k/sun3/sun3ints.c -- Sun-3(x) Linux interrupt handling code
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file COPYING in the main directory of this archive
6  * for more details.
7  */
8
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/kernel_stat.h>
13 #include <linux/interrupt.h>
14 #include <asm/segment.h>
15 #include <asm/intersil.h>
16 #include <asm/oplib.h>
17 #include <asm/sun3ints.h>
18 #include <linux/seq_file.h>
19
20 extern void sun3_leds (unsigned char);
21 static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp);
22
23 void sun3_disable_interrupts(void)
24 {
25         sun3_disable_irq(0);
26 }
27
28 void sun3_enable_interrupts(void)
29 {
30         sun3_enable_irq(0);
31 }
32
33 int led_pattern[8] = {
34        ~(0x80), ~(0x01),
35        ~(0x40), ~(0x02),
36        ~(0x20), ~(0x04),
37        ~(0x10), ~(0x08)
38 };
39
40 volatile unsigned char* sun3_intreg;
41
42 void sun3_insert_irq(irq_node_t **list, irq_node_t *node)
43 {
44 }
45
46 void sun3_delete_irq(irq_node_t **list, void *dev_id)
47 {
48 }
49
50 void sun3_enable_irq(unsigned int irq)
51 {
52         *sun3_intreg |=  (1<<irq);
53 }
54
55 void sun3_disable_irq(unsigned int irq)
56 {
57         *sun3_intreg &= ~(1<<irq);
58 }
59
60 inline void sun3_do_irq(int irq, struct pt_regs *fp)
61 {
62         kstat_cpu(0).irqs[SYS_IRQS + irq]++;
63         *sun3_intreg &= ~(1<<irq);
64         *sun3_intreg |=  (1<<irq);
65 }
66
67 static irqreturn_t sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
68 {
69         sun3_do_irq(irq,fp);
70         if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 2000))
71                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%16000)
72                           /2000]);
73         return IRQ_HANDLED;
74 }
75
76 static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
77 {
78         kstat_cpu(0).irqs[SYS_IRQS + irq]++;
79 #ifdef CONFIG_SUN3
80         intersil_clear();
81 #endif
82         *sun3_intreg &= ~(1<<irq);
83         *sun3_intreg |=  (1<<irq);
84 #ifdef CONFIG_SUN3
85         intersil_clear();
86 #endif
87         do_timer(fp);
88         if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20))
89                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160)
90                 /20]);
91         return IRQ_HANDLED;
92 }
93
94 /* handle requested ints, excepting 5 and 7, which always do the same
95    thing */
96 irqreturn_t (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
97         [0] = sun3_inthandle,
98         [1] = sun3_inthandle,
99         [2] = sun3_inthandle,
100         [3] = sun3_inthandle,
101         [4] = sun3_inthandle,
102         [5] = sun3_int5,
103         [6] = sun3_inthandle,
104         [7] = sun3_int7
105 };
106
107 static const char *dev_names[SYS_IRQS] = {
108         [5] = "timer",
109         [7] = "int7 handler"
110 };
111 static void *dev_ids[SYS_IRQS];
112 static irqreturn_t (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
113         [5] = sun3_int5,
114         [7] = sun3_int7
115 };
116 static irqreturn_t (*sun3_vechandler[SUN3_INT_VECS])(int, void *, struct pt_regs *);
117 static void *vec_ids[SUN3_INT_VECS];
118 static const char *vec_names[SUN3_INT_VECS];
119 static int vec_ints[SUN3_INT_VECS];
120
121
122 int show_sun3_interrupts(struct seq_file *p, void *v)
123 {
124         int i;
125
126         for(i = 0; i < (SUN3_INT_VECS-1); i++) {
127                 if(sun3_vechandler[i] != NULL) {
128                         seq_printf(p, "vec %3d: %10u %s\n", i+64,
129                                    vec_ints[i],
130                                    (vec_names[i]) ? vec_names[i] :
131                                    "sun3_vechandler");
132                 }
133         }
134
135         return 0;
136 }
137
138 static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
139 {
140         if(sun3_inthandler[irq] == NULL)
141                 panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
142
143         kstat_cpu(0).irqs[SYS_IRQS + irq]++;
144         *sun3_intreg &= ~(1<<irq);
145
146         sun3_inthandler[irq](irq, dev_ids[irq], fp);
147         return IRQ_HANDLED;
148 }
149
150 static irqreturn_t sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
151 {
152 //      intersil_clear();
153         return IRQ_HANDLED;
154 }
155
156 void sun3_init_IRQ(void)
157 {
158         int i;
159
160         *sun3_intreg = 1;
161
162         for(i = 0; i < SYS_IRQS; i++)
163         {
164                 if(dev_names[i])
165                         cpu_request_irq(i, sun3_default_handler[i], 0,
166                                         dev_names[i], NULL);
167         }
168
169         for(i = 0; i < 192; i++)
170                 sun3_vechandler[i] = NULL;
171
172         sun3_vechandler[191] = sun3_vec255;
173 }
174
175 int sun3_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
176                       unsigned long flags, const char *devname, void *dev_id)
177 {
178
179         if(irq < SYS_IRQS) {
180                 if(sun3_inthandler[irq] != NULL) {
181                         printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
182                         return 1;
183                 }
184
185                 sun3_inthandler[irq] = handler;
186                 dev_ids[irq] = dev_id;
187                 dev_names[irq] = devname;
188
189                 /* setting devname would be nice */
190                 cpu_request_irq(irq, sun3_default_handler[irq], 0, devname,
191                                 NULL);
192
193                 return 0;
194         } else {
195                 if((irq >= 64) && (irq <= 255)) {
196                         int vec;
197
198                         vec = irq - 64;
199                         if(sun3_vechandler[vec] != NULL) {
200                                 printk("sun3_request_irq: request for vec %d -- already taken!\n", irq);
201                                 return 1;
202                         }
203
204                         sun3_vechandler[vec] = handler;
205                         vec_ids[vec] = dev_id;
206                         vec_names[vec] = devname;
207                         vec_ints[vec] = 0;
208
209                         return 0;
210                 }
211         }
212
213         printk("sun3_request_irq: invalid irq %d\n", irq);
214         return 1;
215
216 }
217
218 void sun3_free_irq(unsigned int irq, void *dev_id)
219 {
220
221         if(irq < SYS_IRQS) {
222                 if(sun3_inthandler[irq] == NULL)
223                         panic("sun3_free_int: attempt to free unused irq %d\n", irq);
224                 if(dev_ids[irq] != dev_id)
225                         panic("sun3_free_int: incorrect dev_id for irq %d\n", irq);
226
227                 sun3_inthandler[irq] = NULL;
228                 return;
229         } else if((irq >= 64) && (irq <= 255)) {
230                 int vec;
231
232                 vec = irq - 64;
233                 if(sun3_vechandler[vec] == NULL)
234                         panic("sun3_free_int: attempt to free unused vector %d\n", irq);
235                 if(vec_ids[irq] != dev_id)
236                         panic("sun3_free_int: incorrect dev_id for vec %d\n", irq);
237
238                 sun3_vechandler[vec] = NULL;
239                 return;
240         } else {
241                 panic("sun3_free_irq: invalid irq %d\n", irq);
242         }
243 }
244
245 irqreturn_t sun3_process_int(int irq, struct pt_regs *regs)
246 {
247
248         if((irq >= 64) && (irq <= 255)) {
249                 int vec;
250
251                 vec = irq - 64;
252                 if(sun3_vechandler[vec] == NULL)
253                         panic ("bad interrupt vector %d received\n",irq);
254
255                 vec_ints[vec]++;
256                 return sun3_vechandler[vec](irq, vec_ids[vec], regs);
257         } else {
258                 panic("sun3_process_int: unable to handle interrupt vector %d\n",
259                       irq);
260         }
261 }