File: /usr/src/linux/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     
19     extern void sun3_leds (unsigned char);
20     
21     void sun3_disable_interrupts(void)
22     {
23     	sun3_disable_irq(0);
24     }
25     
26     void sun3_enable_interrupts(void)
27     {
28     	sun3_enable_irq(0);
29     }	
30     
31     int led_pattern[8] = {
32            ~(0x80), ~(0x01),
33            ~(0x40), ~(0x02),
34            ~(0x20), ~(0x04),
35            ~(0x10), ~(0x08)
36     };
37     
38     volatile unsigned char* sun3_intreg;
39     
40     void sun3_insert_irq(irq_node_t **list, irq_node_t *node)
41     {
42     }
43     
44     void sun3_delete_irq(irq_node_t **list, void *dev_id)
45     {
46     }
47     
48     void sun3_enable_irq(unsigned int irq)
49     {
50     	*sun3_intreg |=  (1<<irq);
51     }
52     
53     void sun3_disable_irq(unsigned int irq)
54     {
55     	*sun3_intreg &= ~(1<<irq);
56     }
57     
58     inline void sun3_do_irq(int irq, struct pt_regs *fp)
59     {
60     	kstat.irqs[0][SYS_IRQS + irq]++;
61     	*sun3_intreg &= ~(1<<irq);
62     	*sun3_intreg |=  (1<<irq);
63     }
64     
65     int sun3_get_irq_list(char *buf)
66     {
67     	return 0;
68     }
69     
70     static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
71     {
72     	sun3_do_irq(irq,fp);
73     	if(!(kstat.irqs[0][SYS_IRQS + irq] % 2000)) 
74     		sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%16000)/2000]);
75     }
76     
77     static void sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
78     {
79             kstat.irqs[0][SYS_IRQS + irq]++;
80     #ifdef CONFIG_SUN3
81     	intersil_clear();
82     #endif
83             *sun3_intreg &= ~(1<<irq);
84             *sun3_intreg |=  (1<<irq);
85     #ifdef CONFIG_SUN3
86     	intersil_clear();
87     #endif
88             do_timer(fp);
89             if(!(kstat.irqs[0][SYS_IRQS + irq] % 20))
90                     sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%160)
91                     /20]);
92     }
93     
94     /* handle requested ints, excepting 5 and 7, which always do the same
95        thing */
96     static void *dev_ids[SYS_IRQS];
97     static void (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
98     	NULL, NULL, NULL, NULL, NULL, sun3_int5, NULL, sun3_int7
99     };
100     static void (*sun3_vechandler[192])(int, void *, struct pt_regs *);
101     static void *vec_ids[192];
102     static char *vec_names[192];
103     
104     static void sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
105     {
106     	if(sun3_inthandler[irq] == NULL)
107     		panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
108     
109             kstat.irqs[0][SYS_IRQS + irq]++;
110             *sun3_intreg &= ~(1<<irq);
111     
112     	sun3_inthandler[irq](irq, dev_ids[irq], fp);
113     }
114     
115     static void sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
116     {
117     //	intersil_clear();
118     }
119     
120     void (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
121     	sun3_inthandle, sun3_inthandle, sun3_inthandle, sun3_inthandle,
122     	sun3_inthandle, sun3_int5, sun3_inthandle, sun3_int7
123     };
124     
125     static char *dev_names[SYS_IRQS] = { NULL, NULL, NULL, NULL, 
126     				     NULL, "timer", NULL, NULL };
127     
128     void sun3_init_IRQ(void)
129     {
130     	int i;
131     
132     	*sun3_intreg = 1;
133     
134     	for(i = 0; i < SYS_IRQS; i++)
135     	{
136     		if(dev_names[i])
137     			sys_request_irq(i, sun3_default_handler[i],
138     					0, dev_names[i], NULL);
139     	}
140     
141     	for(i = 0; i < 192; i++) 
142     		sun3_vechandler[i] = NULL;
143     	
144     	sun3_vechandler[191] = sun3_vec255;
145     }
146                                     
147     int sun3_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
148                           unsigned long flags, const char *devname, void *dev_id)
149     {
150     
151     	if(irq < SYS_IRQS) {
152     		if(sun3_inthandler[irq] != NULL) {
153     			printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
154     			return 1;
155     		}
156     		
157     		sun3_inthandler[irq] = handler;
158     		dev_ids[irq] = dev_id;
159     		dev_names[irq] = devname;
160     		
161     		/* setting devname would be nice */
162     		sys_request_irq(irq, sun3_default_handler[irq], 0, devname, NULL);
163     
164     		return 0;
165     	} else {
166     		if((irq >= 64) && (irq <= 255)) {
167     		        int vec;
168     
169     			vec = irq - 64;
170     			if(sun3_vechandler[vec] != NULL) {
171     				printk("sun3_request_irq: request for vec %d -- already taken!\n", irq);
172     				return 1;
173     			}
174     
175     			sun3_vechandler[vec] = handler;
176     			vec_ids[vec] = dev_id;
177     			vec_names[vec] = devname;
178     			
179     			return 0;
180     		}
181     	}
182     
183     	printk("sun3_request_irq: invalid irq %d\n", irq);
184     	return 1;
185     
186     }
187                             
188     void sun3_free_irq(unsigned int irq, void *dev_id)
189     {
190     
191     	if(irq < SYS_IRQS) {
192     		if(sun3_inthandler[irq] == NULL) 
193     			panic("sun3_free_int: attempt to free unused irq %d\n", irq);
194     		if(dev_ids[irq] != dev_id)
195     			panic("sun3_free_int: incorrect dev_id for irq %d\n", irq);
196     		
197     		sun3_inthandler[irq] = NULL;
198     		return;
199     	} else if((irq >= 64) && (irq <= 255)) {
200     		int vec;
201     
202     		vec = irq - 64;
203     		if(sun3_vechandler[vec] == NULL)
204     			panic("sun3_free_int: attempt to free unused vector %d\n", irq);
205     		if(vec_ids[irq] != dev_id)
206     			panic("sun3_free_int: incorrect dev_id for vec %d\n", irq);
207     		
208     		sun3_vechandler[vec] = NULL;
209     		return;
210     	} else {
211     		panic("sun3_free_irq: invalid irq %d\n", irq);
212     	}		
213     }
214     
215     void sun3_process_int(int irq, struct pt_regs *regs)
216     {
217     
218     	if((irq >= 64) && (irq <= 255)) {
219     		int vec;
220     
221     		vec = irq - 64;
222     		if(sun3_vechandler[vec] == NULL) 
223     			panic ("bad interrupt vector %d received\n",irq);
224     			
225     		sun3_vechandler[vec](irq, vec_ids[vec], regs);
226     		return;
227     	} else {
228     		panic("sun3_process_int: unable to handle interrupt vector %d\n",
229     		      irq);
230     	}
231     }
232