Commit 69961c375288bdab7604e0bb1c8d22999bb8a347

Authored by Geert Uytterhoeven
Committed by Linus Torvalds
1 parent da96d0b58a

[PATCH] m68k/Atari: Interrupt updates

Misc Atari fixes:
  - initialize correct number of atari irqs
  - silence vbl interrupt until it's used by atafb
  - use mdelay() to read clock if necessary

Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 3 changed files with 15 additions and 4 deletions Inline Diff

arch/m68k/atari/ataints.c
1 /* 1 /*
2 * arch/m68k/atari/ataints.c -- Atari Linux interrupt handling code 2 * arch/m68k/atari/ataints.c -- Atari Linux interrupt handling code
3 * 3 *
4 * 5/2/94 Roman Hodek: 4 * 5/2/94 Roman Hodek:
5 * Added support for TT interrupts; setup for TT SCU (may someone has 5 * Added support for TT interrupts; setup for TT SCU (may someone has
6 * twiddled there and we won't get the right interrupts :-() 6 * twiddled there and we won't get the right interrupts :-()
7 * 7 *
8 * Major change: The device-independent code in m68k/ints.c didn't know 8 * Major change: The device-independent code in m68k/ints.c didn't know
9 * about non-autovec ints yet. It hardcoded the number of possible ints to 9 * about non-autovec ints yet. It hardcoded the number of possible ints to
10 * 7 (IRQ1...IRQ7). But the Atari has lots of non-autovec ints! I made the 10 * 7 (IRQ1...IRQ7). But the Atari has lots of non-autovec ints! I made the
11 * number of possible ints a constant defined in interrupt.h, which is 11 * number of possible ints a constant defined in interrupt.h, which is
12 * 47 for the Atari. So we can call request_irq() for all Atari interrupts 12 * 47 for the Atari. So we can call request_irq() for all Atari interrupts
13 * just the normal way. Additionally, all vectors >= 48 are initialized to 13 * just the normal way. Additionally, all vectors >= 48 are initialized to
14 * call trap() instead of inthandler(). This must be changed here, too. 14 * call trap() instead of inthandler(). This must be changed here, too.
15 * 15 *
16 * 1995-07-16 Lars Brinkhoff <f93labr@dd.chalmers.se>: 16 * 1995-07-16 Lars Brinkhoff <f93labr@dd.chalmers.se>:
17 * Corrected a bug in atari_add_isr() which rejected all SCC 17 * Corrected a bug in atari_add_isr() which rejected all SCC
18 * interrupt sources if there were no TT MFP! 18 * interrupt sources if there were no TT MFP!
19 * 19 *
20 * 12/13/95: New interface functions atari_level_triggered_int() and 20 * 12/13/95: New interface functions atari_level_triggered_int() and
21 * atari_register_vme_int() as support for level triggered VME interrupts. 21 * atari_register_vme_int() as support for level triggered VME interrupts.
22 * 22 *
23 * 02/12/96: (Roman) 23 * 02/12/96: (Roman)
24 * Total rewrite of Atari interrupt handling, for new scheme see comments 24 * Total rewrite of Atari interrupt handling, for new scheme see comments
25 * below. 25 * below.
26 * 26 *
27 * 1996-09-03 lars brinkhoff <f93labr@dd.chalmers.se>: 27 * 1996-09-03 lars brinkhoff <f93labr@dd.chalmers.se>:
28 * Added new function atari_unregister_vme_int(), and 28 * Added new function atari_unregister_vme_int(), and
29 * modified atari_register_vme_int() as well as IS_VALID_INTNO() 29 * modified atari_register_vme_int() as well as IS_VALID_INTNO()
30 * to work with it. 30 * to work with it.
31 * 31 *
32 * This file is subject to the terms and conditions of the GNU General Public 32 * This file is subject to the terms and conditions of the GNU General Public
33 * License. See the file COPYING in the main directory of this archive 33 * License. See the file COPYING in the main directory of this archive
34 * for more details. 34 * for more details.
35 * 35 *
36 */ 36 */
37 37
38 #include <linux/types.h> 38 #include <linux/types.h>
39 #include <linux/kernel.h> 39 #include <linux/kernel.h>
40 #include <linux/kernel_stat.h> 40 #include <linux/kernel_stat.h>
41 #include <linux/init.h> 41 #include <linux/init.h>
42 #include <linux/seq_file.h> 42 #include <linux/seq_file.h>
43 43
44 #include <asm/system.h> 44 #include <asm/system.h>
45 #include <asm/traps.h> 45 #include <asm/traps.h>
46 46
47 #include <asm/atarihw.h> 47 #include <asm/atarihw.h>
48 #include <asm/atariints.h> 48 #include <asm/atariints.h>
49 #include <asm/atari_stdma.h> 49 #include <asm/atari_stdma.h>
50 #include <asm/irq.h> 50 #include <asm/irq.h>
51 #include <asm/entry.h> 51 #include <asm/entry.h>
52 52
53 53
54 /* 54 /*
55 * Atari interrupt handling scheme: 55 * Atari interrupt handling scheme:
56 * -------------------------------- 56 * --------------------------------
57 * 57 *
58 * All interrupt source have an internal number (defined in 58 * All interrupt source have an internal number (defined in
59 * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP, 59 * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
60 * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can 60 * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
61 * be allocated by atari_register_vme_int(). 61 * be allocated by atari_register_vme_int().
62 * 62 *
63 * Each interrupt can be of three types: 63 * Each interrupt can be of three types:
64 * 64 *
65 * - SLOW: The handler runs with all interrupts enabled, except the one it 65 * - SLOW: The handler runs with all interrupts enabled, except the one it
66 * was called by (to avoid reentering). This should be the usual method. 66 * was called by (to avoid reentering). This should be the usual method.
67 * But it is currently possible only for MFP ints, since only the MFP 67 * But it is currently possible only for MFP ints, since only the MFP
68 * offers an easy way to mask interrupts. 68 * offers an easy way to mask interrupts.
69 * 69 *
70 * - FAST: The handler runs with all interrupts disabled. This should be used 70 * - FAST: The handler runs with all interrupts disabled. This should be used
71 * only for really fast handlers, that just do actions immediately 71 * only for really fast handlers, that just do actions immediately
72 * necessary, and let the rest do a bottom half or task queue. 72 * necessary, and let the rest do a bottom half or task queue.
73 * 73 *
74 * - PRIORITIZED: The handler can be interrupted by higher-level ints 74 * - PRIORITIZED: The handler can be interrupted by higher-level ints
75 * (greater IPL, no MFP priorities!). This is the method of choice for ints 75 * (greater IPL, no MFP priorities!). This is the method of choice for ints
76 * which should be slow, but are not from a MFP. 76 * which should be slow, but are not from a MFP.
77 * 77 *
78 * The feature of more than one handler for one int source is still there, but 78 * The feature of more than one handler for one int source is still there, but
79 * only applicable if all handers are of the same type. To not slow down 79 * only applicable if all handers are of the same type. To not slow down
80 * processing of ints with only one handler by the chaining feature, the list 80 * processing of ints with only one handler by the chaining feature, the list
81 * calling function atari_call_irq_list() is only plugged in at the time the 81 * calling function atari_call_irq_list() is only plugged in at the time the
82 * second handler is registered. 82 * second handler is registered.
83 * 83 *
84 * Implementation notes: For fast-as-possible int handling, there are separate 84 * Implementation notes: For fast-as-possible int handling, there are separate
85 * entry points for each type (slow/fast/prio). The assembler handler calls 85 * entry points for each type (slow/fast/prio). The assembler handler calls
86 * the irq directly in the usual case, no C wrapper is involved. In case of 86 * the irq directly in the usual case, no C wrapper is involved. In case of
87 * multiple handlers, atari_call_irq_list() is registered as handler and calls 87 * multiple handlers, atari_call_irq_list() is registered as handler and calls
88 * in turn the real irq's. To ease access from assembler level to the irq 88 * in turn the real irq's. To ease access from assembler level to the irq
89 * function pointer and accompanying data, these two are stored in a separate 89 * function pointer and accompanying data, these two are stored in a separate
90 * array, irq_handler[]. The rest of data (type, name) are put into a second 90 * array, irq_handler[]. The rest of data (type, name) are put into a second
91 * array, irq_param, that is accessed from C only. For each slow interrupt (32 91 * array, irq_param, that is accessed from C only. For each slow interrupt (32
92 * in all) there are separate handler functions, which makes it possible to 92 * in all) there are separate handler functions, which makes it possible to
93 * hard-code the MFP register address and value, are necessary to mask the 93 * hard-code the MFP register address and value, are necessary to mask the
94 * int. If there'd be only one generic function, lots of calculations would be 94 * int. If there'd be only one generic function, lots of calculations would be
95 * needed to determine MFP register and int mask from the vector number :-( 95 * needed to determine MFP register and int mask from the vector number :-(
96 * 96 *
97 * Furthermore, slow ints may not lower the IPL below its previous value 97 * Furthermore, slow ints may not lower the IPL below its previous value
98 * (before the int happened). This is needed so that an int of class PRIO, on 98 * (before the int happened). This is needed so that an int of class PRIO, on
99 * that this int may be stacked, cannot be reentered. This feature is 99 * that this int may be stacked, cannot be reentered. This feature is
100 * implemented as follows: If the stack frame format is 1 (throwaway), the int 100 * implemented as follows: If the stack frame format is 1 (throwaway), the int
101 * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level 101 * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
102 * 2, which still blocks the HSYNC, but no interrupts of interest. If the 102 * 2, which still blocks the HSYNC, but no interrupts of interest. If the
103 * frame format is 0, the int is nested, and the old IPL value can be found in 103 * frame format is 0, the int is nested, and the old IPL value can be found in
104 * the sr copy in the frame. 104 * the sr copy in the frame.
105 */ 105 */
106 106
107 #if 0 107 #if 0
108 108
109 #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES) 109 #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
110 110
111 typedef void (*asm_irq_handler)(void); 111 typedef void (*asm_irq_handler)(void);
112 112
113 struct irqhandler { 113 struct irqhandler {
114 irqreturn_t (*handler)(int, void *, struct pt_regs *); 114 irqreturn_t (*handler)(int, void *, struct pt_regs *);
115 void *dev_id; 115 void *dev_id;
116 }; 116 };
117 117
118 struct irqparam { 118 struct irqparam {
119 unsigned long flags; 119 unsigned long flags;
120 const char *devname; 120 const char *devname;
121 }; 121 };
122 122
123 /* 123 /*
124 * Array with irq's and their parameter data. This array is accessed from low 124 * Array with irq's and their parameter data. This array is accessed from low
125 * level assembler code, so an element size of 8 allows usage of index scaling 125 * level assembler code, so an element size of 8 allows usage of index scaling
126 * addressing mode. 126 * addressing mode.
127 */ 127 */
128 static struct irqhandler irq_handler[NUM_INT_SOURCES]; 128 static struct irqhandler irq_handler[NUM_INT_SOURCES];
129 129
130 /* 130 /*
131 * This array hold the rest of parameters of int handlers: type 131 * This array hold the rest of parameters of int handlers: type
132 * (slow,fast,prio) and the name of the handler. These values are only 132 * (slow,fast,prio) and the name of the handler. These values are only
133 * accessed from C 133 * accessed from C
134 */ 134 */
135 static struct irqparam irq_param[NUM_INT_SOURCES]; 135 static struct irqparam irq_param[NUM_INT_SOURCES];
136 136
137 /* check for valid int number (complex, sigh...) */ 137 /* check for valid int number (complex, sigh...) */
138 #define IS_VALID_INTNO(n) \ 138 #define IS_VALID_INTNO(n) \
139 ((n) > 0 && \ 139 ((n) > 0 && \
140 /* autovec and ST-MFP ok anyway */ \ 140 /* autovec and ST-MFP ok anyway */ \
141 (((n) < TTMFP_SOURCE_BASE) || \ 141 (((n) < TTMFP_SOURCE_BASE) || \
142 /* TT-MFP ok if present */ \ 142 /* TT-MFP ok if present */ \
143 ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \ 143 ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE && \
144 ATARIHW_PRESENT(TT_MFP)) || \ 144 ATARIHW_PRESENT(TT_MFP)) || \
145 /* SCC ok if present and number even */ \ 145 /* SCC ok if present and number even */ \
146 ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \ 146 ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE && \
147 !((n) & 1) && ATARIHW_PRESENT(SCC)) || \ 147 !((n) & 1) && ATARIHW_PRESENT(SCC)) || \
148 /* greater numbers ok if they are registered VME vectors */ \ 148 /* greater numbers ok if they are registered VME vectors */ \
149 ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \ 149 ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
150 free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE))))) 150 free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
151 151
152 152
153 /* 153 /*
154 * Here start the assembler entry points for interrupts 154 * Here start the assembler entry points for interrupts
155 */ 155 */
156 156
157 #define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void) 157 #define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
158 158
159 #define BUILD_SLOW_IRQ(n) \ 159 #define BUILD_SLOW_IRQ(n) \
160 asmlinkage void IRQ_NAME(n); \ 160 asmlinkage void IRQ_NAME(n); \
161 /* Dummy function to allow asm with operands. */ \ 161 /* Dummy function to allow asm with operands. */ \
162 void atari_slow_irq_##n##_dummy (void) { \ 162 void atari_slow_irq_##n##_dummy (void) { \
163 __asm__ (__ALIGN_STR "\n" \ 163 __asm__ (__ALIGN_STR "\n" \
164 "atari_slow_irq_" #n "_handler:\t" \ 164 "atari_slow_irq_" #n "_handler:\t" \
165 " addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \ 165 " addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \
166 SAVE_ALL_INT "\n" \ 166 SAVE_ALL_INT "\n" \
167 GET_CURRENT(%%d0) "\n" \ 167 GET_CURRENT(%%d0) "\n" \
168 " andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \ 168 " andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \
169 /* get old IPL from stack frame */ \ 169 /* get old IPL from stack frame */ \
170 " bfextu %%sp@(%c2){#5,#3},%%d0\n" \ 170 " bfextu %%sp@(%c2){#5,#3},%%d0\n" \
171 " movew %%sr,%%d1\n" \ 171 " movew %%sr,%%d1\n" \
172 " bfins %%d0,%%d1{#21,#3}\n" \ 172 " bfins %%d0,%%d1{#21,#3}\n" \
173 " movew %%d1,%%sr\n" /* set IPL = previous value */ \ 173 " movew %%d1,%%sr\n" /* set IPL = previous value */ \
174 " addql #1,%a0\n" \ 174 " addql #1,%a0\n" \
175 " lea %a1,%%a0\n" \ 175 " lea %a1,%%a0\n" \
176 " pea %%sp@\n" /* push addr of frame */ \ 176 " pea %%sp@\n" /* push addr of frame */ \
177 " movel %%a0@(4),%%sp@-\n" /* push handler data */ \ 177 " movel %%a0@(4),%%sp@-\n" /* push handler data */ \
178 " pea (%c3+8)\n" /* push int number */ \ 178 " pea (%c3+8)\n" /* push int number */ \
179 " movel %%a0@,%%a0\n" \ 179 " movel %%a0@,%%a0\n" \
180 " jbsr %%a0@\n" /* call the handler */ \ 180 " jbsr %%a0@\n" /* call the handler */ \
181 " addql #8,%%sp\n" \ 181 " addql #8,%%sp\n" \
182 " addql #4,%%sp\n" \ 182 " addql #4,%%sp\n" \
183 " orw #0x0600,%%sr\n" \ 183 " orw #0x0600,%%sr\n" \
184 " andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \ 184 " andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \
185 " orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \ 185 " orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \
186 " jbra ret_from_interrupt\n" \ 186 " jbra ret_from_interrupt\n" \
187 : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \ 187 : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]), \
188 "n" (PT_OFF_SR), "n" (n), \ 188 "n" (PT_OFF_SR), "n" (n), \
189 "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \ 189 "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \
190 : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \ 190 : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \
191 "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \ 191 "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \
192 ); \ 192 ); \
193 for (;;); /* fake noreturn */ \ 193 for (;;); /* fake noreturn */ \
194 } 194 }
195 195
196 BUILD_SLOW_IRQ(0); 196 BUILD_SLOW_IRQ(0);
197 BUILD_SLOW_IRQ(1); 197 BUILD_SLOW_IRQ(1);
198 BUILD_SLOW_IRQ(2); 198 BUILD_SLOW_IRQ(2);
199 BUILD_SLOW_IRQ(3); 199 BUILD_SLOW_IRQ(3);
200 BUILD_SLOW_IRQ(4); 200 BUILD_SLOW_IRQ(4);
201 BUILD_SLOW_IRQ(5); 201 BUILD_SLOW_IRQ(5);
202 BUILD_SLOW_IRQ(6); 202 BUILD_SLOW_IRQ(6);
203 BUILD_SLOW_IRQ(7); 203 BUILD_SLOW_IRQ(7);
204 BUILD_SLOW_IRQ(8); 204 BUILD_SLOW_IRQ(8);
205 BUILD_SLOW_IRQ(9); 205 BUILD_SLOW_IRQ(9);
206 BUILD_SLOW_IRQ(10); 206 BUILD_SLOW_IRQ(10);
207 BUILD_SLOW_IRQ(11); 207 BUILD_SLOW_IRQ(11);
208 BUILD_SLOW_IRQ(12); 208 BUILD_SLOW_IRQ(12);
209 BUILD_SLOW_IRQ(13); 209 BUILD_SLOW_IRQ(13);
210 BUILD_SLOW_IRQ(14); 210 BUILD_SLOW_IRQ(14);
211 BUILD_SLOW_IRQ(15); 211 BUILD_SLOW_IRQ(15);
212 BUILD_SLOW_IRQ(16); 212 BUILD_SLOW_IRQ(16);
213 BUILD_SLOW_IRQ(17); 213 BUILD_SLOW_IRQ(17);
214 BUILD_SLOW_IRQ(18); 214 BUILD_SLOW_IRQ(18);
215 BUILD_SLOW_IRQ(19); 215 BUILD_SLOW_IRQ(19);
216 BUILD_SLOW_IRQ(20); 216 BUILD_SLOW_IRQ(20);
217 BUILD_SLOW_IRQ(21); 217 BUILD_SLOW_IRQ(21);
218 BUILD_SLOW_IRQ(22); 218 BUILD_SLOW_IRQ(22);
219 BUILD_SLOW_IRQ(23); 219 BUILD_SLOW_IRQ(23);
220 BUILD_SLOW_IRQ(24); 220 BUILD_SLOW_IRQ(24);
221 BUILD_SLOW_IRQ(25); 221 BUILD_SLOW_IRQ(25);
222 BUILD_SLOW_IRQ(26); 222 BUILD_SLOW_IRQ(26);
223 BUILD_SLOW_IRQ(27); 223 BUILD_SLOW_IRQ(27);
224 BUILD_SLOW_IRQ(28); 224 BUILD_SLOW_IRQ(28);
225 BUILD_SLOW_IRQ(29); 225 BUILD_SLOW_IRQ(29);
226 BUILD_SLOW_IRQ(30); 226 BUILD_SLOW_IRQ(30);
227 BUILD_SLOW_IRQ(31); 227 BUILD_SLOW_IRQ(31);
228 228
229 asm_irq_handler slow_handlers[32] = { 229 asm_irq_handler slow_handlers[32] = {
230 [0] = atari_slow_irq_0_handler, 230 [0] = atari_slow_irq_0_handler,
231 [1] = atari_slow_irq_1_handler, 231 [1] = atari_slow_irq_1_handler,
232 [2] = atari_slow_irq_2_handler, 232 [2] = atari_slow_irq_2_handler,
233 [3] = atari_slow_irq_3_handler, 233 [3] = atari_slow_irq_3_handler,
234 [4] = atari_slow_irq_4_handler, 234 [4] = atari_slow_irq_4_handler,
235 [5] = atari_slow_irq_5_handler, 235 [5] = atari_slow_irq_5_handler,
236 [6] = atari_slow_irq_6_handler, 236 [6] = atari_slow_irq_6_handler,
237 [7] = atari_slow_irq_7_handler, 237 [7] = atari_slow_irq_7_handler,
238 [8] = atari_slow_irq_8_handler, 238 [8] = atari_slow_irq_8_handler,
239 [9] = atari_slow_irq_9_handler, 239 [9] = atari_slow_irq_9_handler,
240 [10] = atari_slow_irq_10_handler, 240 [10] = atari_slow_irq_10_handler,
241 [11] = atari_slow_irq_11_handler, 241 [11] = atari_slow_irq_11_handler,
242 [12] = atari_slow_irq_12_handler, 242 [12] = atari_slow_irq_12_handler,
243 [13] = atari_slow_irq_13_handler, 243 [13] = atari_slow_irq_13_handler,
244 [14] = atari_slow_irq_14_handler, 244 [14] = atari_slow_irq_14_handler,
245 [15] = atari_slow_irq_15_handler, 245 [15] = atari_slow_irq_15_handler,
246 [16] = atari_slow_irq_16_handler, 246 [16] = atari_slow_irq_16_handler,
247 [17] = atari_slow_irq_17_handler, 247 [17] = atari_slow_irq_17_handler,
248 [18] = atari_slow_irq_18_handler, 248 [18] = atari_slow_irq_18_handler,
249 [19] = atari_slow_irq_19_handler, 249 [19] = atari_slow_irq_19_handler,
250 [20] = atari_slow_irq_20_handler, 250 [20] = atari_slow_irq_20_handler,
251 [21] = atari_slow_irq_21_handler, 251 [21] = atari_slow_irq_21_handler,
252 [22] = atari_slow_irq_22_handler, 252 [22] = atari_slow_irq_22_handler,
253 [23] = atari_slow_irq_23_handler, 253 [23] = atari_slow_irq_23_handler,
254 [24] = atari_slow_irq_24_handler, 254 [24] = atari_slow_irq_24_handler,
255 [25] = atari_slow_irq_25_handler, 255 [25] = atari_slow_irq_25_handler,
256 [26] = atari_slow_irq_26_handler, 256 [26] = atari_slow_irq_26_handler,
257 [27] = atari_slow_irq_27_handler, 257 [27] = atari_slow_irq_27_handler,
258 [28] = atari_slow_irq_28_handler, 258 [28] = atari_slow_irq_28_handler,
259 [29] = atari_slow_irq_29_handler, 259 [29] = atari_slow_irq_29_handler,
260 [30] = atari_slow_irq_30_handler, 260 [30] = atari_slow_irq_30_handler,
261 [31] = atari_slow_irq_31_handler 261 [31] = atari_slow_irq_31_handler
262 }; 262 };
263 263
264 asmlinkage void atari_fast_irq_handler( void ); 264 asmlinkage void atari_fast_irq_handler( void );
265 asmlinkage void atari_prio_irq_handler( void ); 265 asmlinkage void atari_prio_irq_handler( void );
266 266
267 /* Dummy function to allow asm with operands. */ 267 /* Dummy function to allow asm with operands. */
268 void atari_fast_prio_irq_dummy (void) { 268 void atari_fast_prio_irq_dummy (void) {
269 __asm__ (__ALIGN_STR "\n" 269 __asm__ (__ALIGN_STR "\n"
270 "atari_fast_irq_handler:\n\t" 270 "atari_fast_irq_handler:\n\t"
271 "orw #0x700,%%sr\n" /* disable all interrupts */ 271 "orw #0x700,%%sr\n" /* disable all interrupts */
272 "atari_prio_irq_handler:\n\t" 272 "atari_prio_irq_handler:\n\t"
273 "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */ 273 "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */
274 SAVE_ALL_INT "\n\t" 274 SAVE_ALL_INT "\n\t"
275 GET_CURRENT(%%d0) "\n\t" 275 GET_CURRENT(%%d0) "\n\t"
276 /* get vector number from stack frame and convert to source */ 276 /* get vector number from stack frame and convert to source */
277 "bfextu %%sp@(%c1){#4,#10},%%d0\n\t" 277 "bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
278 "subw #(0x40-8),%%d0\n\t" 278 "subw #(0x40-8),%%d0\n\t"
279 "jpl 1f\n\t" 279 "jpl 1f\n\t"
280 "addw #(0x40-8-0x18),%%d0\n" 280 "addw #(0x40-8-0x18),%%d0\n"
281 "1:\tlea %a0,%%a0\n\t" 281 "1:\tlea %a0,%%a0\n\t"
282 "addql #1,%%a0@(%%d0:l:4)\n\t" 282 "addql #1,%%a0@(%%d0:l:4)\n\t"
283 "lea irq_handler,%%a0\n\t" 283 "lea irq_handler,%%a0\n\t"
284 "lea %%a0@(%%d0:l:8),%%a0\n\t" 284 "lea %%a0@(%%d0:l:8),%%a0\n\t"
285 "pea %%sp@\n\t" /* push frame address */ 285 "pea %%sp@\n\t" /* push frame address */
286 "movel %%a0@(4),%%sp@-\n\t" /* push handler data */ 286 "movel %%a0@(4),%%sp@-\n\t" /* push handler data */
287 "movel %%d0,%%sp@-\n\t" /* push int number */ 287 "movel %%d0,%%sp@-\n\t" /* push int number */
288 "movel %%a0@,%%a0\n\t" 288 "movel %%a0@,%%a0\n\t"
289 "jsr %%a0@\n\t" /* and call the handler */ 289 "jsr %%a0@\n\t" /* and call the handler */
290 "addql #8,%%sp\n\t" 290 "addql #8,%%sp\n\t"
291 "addql #4,%%sp\n\t" 291 "addql #4,%%sp\n\t"
292 "jbra ret_from_interrupt" 292 "jbra ret_from_interrupt"
293 : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC), 293 : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
294 "m" (preempt_count()), "di" (HARDIRQ_OFFSET) 294 "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
295 ); 295 );
296 for (;;); 296 for (;;);
297 } 297 }
298 #endif 298 #endif
299 299
300 /* 300 /*
301 * Bitmap for free interrupt vector numbers 301 * Bitmap for free interrupt vector numbers
302 * (new vectors starting from 0x70 can be allocated by 302 * (new vectors starting from 0x70 can be allocated by
303 * atari_register_vme_int()) 303 * atari_register_vme_int())
304 */ 304 */
305 static int free_vme_vec_bitmap; 305 static int free_vme_vec_bitmap;
306 306
307 /* GK: 307 /* GK:
308 * HBL IRQ handler for Falcon. Nobody needs it :-) 308 * HBL IRQ handler for Falcon. Nobody needs it :-)
309 * ++andreas: raise ipl to disable further HBLANK interrupts. 309 * ++andreas: raise ipl to disable further HBLANK interrupts.
310 */ 310 */
311 asmlinkage void falcon_hblhandler(void); 311 asmlinkage void falcon_hblhandler(void);
312 asm(".text\n" 312 asm(".text\n"
313 __ALIGN_STR "\n\t" 313 __ALIGN_STR "\n\t"
314 "falcon_hblhandler:\n\t" 314 "falcon_hblhandler:\n\t"
315 "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ 315 "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */
316 "rte"); 316 "rte");
317 317
318 extern void atari_microwire_cmd(int cmd); 318 extern void atari_microwire_cmd(int cmd);
319 319
320 extern int atari_SCC_reset_done; 320 extern int atari_SCC_reset_done;
321 321
322 static int atari_startup_irq(unsigned int irq) 322 static int atari_startup_irq(unsigned int irq)
323 { 323 {
324 m68k_irq_startup(irq); 324 m68k_irq_startup(irq);
325 atari_turnon_irq(irq); 325 atari_turnon_irq(irq);
326 atari_enable_irq(irq); 326 atari_enable_irq(irq);
327 return 0; 327 return 0;
328 } 328 }
329 329
330 static void atari_shutdown_irq(unsigned int irq) 330 static void atari_shutdown_irq(unsigned int irq)
331 { 331 {
332 atari_disable_irq(irq); 332 atari_disable_irq(irq);
333 atari_turnoff_irq(irq); 333 atari_turnoff_irq(irq);
334 m68k_irq_shutdown(irq); 334 m68k_irq_shutdown(irq);
335
336 if (irq == IRQ_AUTO_4)
337 vectors[VEC_INT4] = falcon_hblhandler;
335 } 338 }
336 339
337 static struct irq_controller atari_irq_controller = { 340 static struct irq_controller atari_irq_controller = {
338 .name = "atari", 341 .name = "atari",
339 .lock = SPIN_LOCK_UNLOCKED, 342 .lock = SPIN_LOCK_UNLOCKED,
340 .startup = atari_startup_irq, 343 .startup = atari_startup_irq,
341 .shutdown = atari_shutdown_irq, 344 .shutdown = atari_shutdown_irq,
342 .enable = atari_enable_irq, 345 .enable = atari_enable_irq,
343 .disable = atari_disable_irq, 346 .disable = atari_disable_irq,
344 }; 347 };
345 348
346 /* 349 /*
347 * void atari_init_IRQ (void) 350 * void atari_init_IRQ (void)
348 * 351 *
349 * Parameters: None 352 * Parameters: None
350 * 353 *
351 * Returns: Nothing 354 * Returns: Nothing
352 * 355 *
353 * This function should be called during kernel startup to initialize 356 * This function should be called during kernel startup to initialize
354 * the atari IRQ handling routines. 357 * the atari IRQ handling routines.
355 */ 358 */
356 359
357 void __init atari_init_IRQ(void) 360 void __init atari_init_IRQ(void)
358 { 361 {
359 m68k_setup_user_interrupt(VEC_USER, 192, NULL); 362 m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
360 m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1); 363 m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
361 364
362 /* Initialize the MFP(s) */ 365 /* Initialize the MFP(s) */
363 366
364 #ifdef ATARI_USE_SOFTWARE_EOI 367 #ifdef ATARI_USE_SOFTWARE_EOI
365 mfp.vec_adr = 0x48; /* Software EOI-Mode */ 368 mfp.vec_adr = 0x48; /* Software EOI-Mode */
366 #else 369 #else
367 mfp.vec_adr = 0x40; /* Automatic EOI-Mode */ 370 mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
368 #endif 371 #endif
369 mfp.int_en_a = 0x00; /* turn off MFP-Ints */ 372 mfp.int_en_a = 0x00; /* turn off MFP-Ints */
370 mfp.int_en_b = 0x00; 373 mfp.int_en_b = 0x00;
371 mfp.int_mk_a = 0xff; /* no Masking */ 374 mfp.int_mk_a = 0xff; /* no Masking */
372 mfp.int_mk_b = 0xff; 375 mfp.int_mk_b = 0xff;
373 376
374 if (ATARIHW_PRESENT(TT_MFP)) { 377 if (ATARIHW_PRESENT(TT_MFP)) {
375 #ifdef ATARI_USE_SOFTWARE_EOI 378 #ifdef ATARI_USE_SOFTWARE_EOI
376 tt_mfp.vec_adr = 0x58; /* Software EOI-Mode */ 379 tt_mfp.vec_adr = 0x58; /* Software EOI-Mode */
377 #else 380 #else
378 tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */ 381 tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */
379 #endif 382 #endif
380 tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */ 383 tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
381 tt_mfp.int_en_b = 0x00; 384 tt_mfp.int_en_b = 0x00;
382 tt_mfp.int_mk_a = 0xff; /* no Masking */ 385 tt_mfp.int_mk_a = 0xff; /* no Masking */
383 tt_mfp.int_mk_b = 0xff; 386 tt_mfp.int_mk_b = 0xff;
384 } 387 }
385 388
386 if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) { 389 if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) {
387 scc.cha_a_ctrl = 9; 390 scc.cha_a_ctrl = 9;
388 MFPDELAY(); 391 MFPDELAY();
389 scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */ 392 scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
390 } 393 }
391 394
392 if (ATARIHW_PRESENT(SCU)) { 395 if (ATARIHW_PRESENT(SCU)) {
393 /* init the SCU if present */ 396 /* init the SCU if present */
394 tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and 397 tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and
395 * disable HSYNC interrupts (who 398 * disable HSYNC interrupts (who
396 * needs them?) MFP and SCC are 399 * needs them?) MFP and SCC are
397 * enabled in VME mask 400 * enabled in VME mask
398 */ 401 */
399 tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ 402 tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */
400 } else { 403 } else {
401 /* If no SCU and no Hades, the HSYNC interrupt needs to be 404 /* If no SCU and no Hades, the HSYNC interrupt needs to be
402 * disabled this way. (Else _inthandler in kernel/sys_call.S 405 * disabled this way. (Else _inthandler in kernel/sys_call.S
403 * gets overruns) 406 * gets overruns)
404 */ 407 */
405 408
406 if (!MACH_IS_HADES) 409 if (!MACH_IS_HADES) {
407 vectors[VEC_INT2] = falcon_hblhandler; 410 vectors[VEC_INT2] = falcon_hblhandler;
411 vectors[VEC_INT4] = falcon_hblhandler;
412 }
408 } 413 }
409 414
410 if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) { 415 if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
411 /* Initialize the LM1992 Sound Controller to enable 416 /* Initialize the LM1992 Sound Controller to enable
412 the PSG sound. This is misplaced here, it should 417 the PSG sound. This is misplaced here, it should
413 be in an atasound_init(), that doesn't exist yet. */ 418 be in an atasound_init(), that doesn't exist yet. */
414 atari_microwire_cmd(MW_LM1992_PSG_HIGH); 419 atari_microwire_cmd(MW_LM1992_PSG_HIGH);
415 } 420 }
416 421
417 stdma_init(); 422 stdma_init();
418 423
419 /* Initialize the PSG: all sounds off, both ports output */ 424 /* Initialize the PSG: all sounds off, both ports output */
420 sound_ym.rd_data_reg_sel = 7; 425 sound_ym.rd_data_reg_sel = 7;
421 sound_ym.wd_data = 0xff; 426 sound_ym.wd_data = 0xff;
422 } 427 }
423 428
424 429
425 /* 430 /*
426 * atari_register_vme_int() returns the number of a free interrupt vector for 431 * atari_register_vme_int() returns the number of a free interrupt vector for
427 * hardware with a programmable int vector (probably a VME board). 432 * hardware with a programmable int vector (probably a VME board).
428 */ 433 */
429 434
430 unsigned long atari_register_vme_int(void) 435 unsigned long atari_register_vme_int(void)
431 { 436 {
432 int i; 437 int i;
433 438
434 for (i = 0; i < 32; i++) 439 for (i = 0; i < 32; i++)
435 if ((free_vme_vec_bitmap & (1 << i)) == 0) 440 if ((free_vme_vec_bitmap & (1 << i)) == 0)
436 break; 441 break;
437 442
438 if (i == 16) 443 if (i == 16)
439 return 0; 444 return 0;
440 445
441 free_vme_vec_bitmap |= 1 << i; 446 free_vme_vec_bitmap |= 1 << i;
442 return VME_SOURCE_BASE + i; 447 return VME_SOURCE_BASE + i;
443 } 448 }
444 449
445 450
446 void atari_unregister_vme_int(unsigned long irq) 451 void atari_unregister_vme_int(unsigned long irq)
447 { 452 {
448 if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { 453 if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
449 irq -= VME_SOURCE_BASE; 454 irq -= VME_SOURCE_BASE;
450 free_vme_vec_bitmap &= ~(1 << irq); 455 free_vme_vec_bitmap &= ~(1 << irq);
451 } 456 }
452 } 457 }
453 458
454 459
455 460
arch/m68k/atari/time.c
1 /* 1 /*
2 * linux/arch/m68k/atari/time.c 2 * linux/arch/m68k/atari/time.c
3 * 3 *
4 * Atari time and real time clock stuff 4 * Atari time and real time clock stuff
5 * 5 *
6 * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek 6 * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
7 * 7 *
8 * This file is subject to the terms and conditions of the GNU General Public 8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive 9 * License. See the file COPYING in the main directory of this archive
10 * for more details. 10 * for more details.
11 */ 11 */
12 12
13 #include <linux/types.h> 13 #include <linux/types.h>
14 #include <linux/mc146818rtc.h> 14 #include <linux/mc146818rtc.h>
15 #include <linux/interrupt.h> 15 #include <linux/interrupt.h>
16 #include <linux/init.h> 16 #include <linux/init.h>
17 #include <linux/rtc.h> 17 #include <linux/rtc.h>
18 #include <linux/bcd.h> 18 #include <linux/bcd.h>
19 #include <linux/delay.h>
19 20
20 #include <asm/atariints.h> 21 #include <asm/atariints.h>
21 22
22 void __init 23 void __init
23 atari_sched_init(irq_handler_t timer_routine) 24 atari_sched_init(irq_handler_t timer_routine)
24 { 25 {
25 /* set Timer C data Register */ 26 /* set Timer C data Register */
26 mfp.tim_dt_c = INT_TICKS; 27 mfp.tim_dt_c = INT_TICKS;
27 /* start timer C, div = 1:100 */ 28 /* start timer C, div = 1:100 */
28 mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60; 29 mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
29 /* install interrupt service routine for MFP Timer C */ 30 /* install interrupt service routine for MFP Timer C */
30 request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW, 31 request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
31 "timer", timer_routine); 32 "timer", timer_routine);
32 } 33 }
33 34
34 /* ++andreas: gettimeoffset fixed to check for pending interrupt */ 35 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
35 36
36 #define TICK_SIZE 10000 37 #define TICK_SIZE 10000
37 38
38 /* This is always executed with interrupts disabled. */ 39 /* This is always executed with interrupts disabled. */
39 unsigned long atari_gettimeoffset (void) 40 unsigned long atari_gettimeoffset (void)
40 { 41 {
41 unsigned long ticks, offset = 0; 42 unsigned long ticks, offset = 0;
42 43
43 /* read MFP timer C current value */ 44 /* read MFP timer C current value */
44 ticks = mfp.tim_dt_c; 45 ticks = mfp.tim_dt_c;
45 /* The probability of underflow is less than 2% */ 46 /* The probability of underflow is less than 2% */
46 if (ticks > INT_TICKS - INT_TICKS / 50) 47 if (ticks > INT_TICKS - INT_TICKS / 50)
47 /* Check for pending timer interrupt */ 48 /* Check for pending timer interrupt */
48 if (mfp.int_pn_b & (1 << 5)) 49 if (mfp.int_pn_b & (1 << 5))
49 offset = TICK_SIZE; 50 offset = TICK_SIZE;
50 51
51 ticks = INT_TICKS - ticks; 52 ticks = INT_TICKS - ticks;
52 ticks = ticks * 10000L / INT_TICKS; 53 ticks = ticks * 10000L / INT_TICKS;
53 54
54 return ticks + offset; 55 return ticks + offset;
55 } 56 }
56 57
57 58
58 static void mste_read(struct MSTE_RTC *val) 59 static void mste_read(struct MSTE_RTC *val)
59 { 60 {
60 #define COPY(v) val->v=(mste_rtc.v & 0xf) 61 #define COPY(v) val->v=(mste_rtc.v & 0xf)
61 do { 62 do {
62 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ; 63 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
63 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ; 64 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
64 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ; 65 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
65 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ; 66 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
66 COPY(year_tens) ; 67 COPY(year_tens) ;
67 /* prevent from reading the clock while it changed */ 68 /* prevent from reading the clock while it changed */
68 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf)); 69 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
69 #undef COPY 70 #undef COPY
70 } 71 }
71 72
72 static void mste_write(struct MSTE_RTC *val) 73 static void mste_write(struct MSTE_RTC *val)
73 { 74 {
74 #define COPY(v) mste_rtc.v=val->v 75 #define COPY(v) mste_rtc.v=val->v
75 do { 76 do {
76 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ; 77 COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
77 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ; 78 COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
78 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ; 79 COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
79 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ; 80 COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
80 COPY(year_tens) ; 81 COPY(year_tens) ;
81 /* prevent from writing the clock while it changed */ 82 /* prevent from writing the clock while it changed */
82 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf)); 83 } while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
83 #undef COPY 84 #undef COPY
84 } 85 }
85 86
86 #define RTC_READ(reg) \ 87 #define RTC_READ(reg) \
87 ({ unsigned char __val; \ 88 ({ unsigned char __val; \
88 (void) atari_writeb(reg,&tt_rtc.regsel); \ 89 (void) atari_writeb(reg,&tt_rtc.regsel); \
89 __val = tt_rtc.data; \ 90 __val = tt_rtc.data; \
90 __val; \ 91 __val; \
91 }) 92 })
92 93
93 #define RTC_WRITE(reg,val) \ 94 #define RTC_WRITE(reg,val) \
94 do { \ 95 do { \
95 atari_writeb(reg,&tt_rtc.regsel); \ 96 atari_writeb(reg,&tt_rtc.regsel); \
96 tt_rtc.data = (val); \ 97 tt_rtc.data = (val); \
97 } while(0) 98 } while(0)
98 99
99 100
100 #define HWCLK_POLL_INTERVAL 5 101 #define HWCLK_POLL_INTERVAL 5
101 102
102 int atari_mste_hwclk( int op, struct rtc_time *t ) 103 int atari_mste_hwclk( int op, struct rtc_time *t )
103 { 104 {
104 int hour, year; 105 int hour, year;
105 int hr24=0; 106 int hr24=0;
106 struct MSTE_RTC val; 107 struct MSTE_RTC val;
107 108
108 mste_rtc.mode=(mste_rtc.mode | 1); 109 mste_rtc.mode=(mste_rtc.mode | 1);
109 hr24=mste_rtc.mon_tens & 1; 110 hr24=mste_rtc.mon_tens & 1;
110 mste_rtc.mode=(mste_rtc.mode & ~1); 111 mste_rtc.mode=(mste_rtc.mode & ~1);
111 112
112 if (op) { 113 if (op) {
113 /* write: prepare values */ 114 /* write: prepare values */
114 115
115 val.sec_ones = t->tm_sec % 10; 116 val.sec_ones = t->tm_sec % 10;
116 val.sec_tens = t->tm_sec / 10; 117 val.sec_tens = t->tm_sec / 10;
117 val.min_ones = t->tm_min % 10; 118 val.min_ones = t->tm_min % 10;
118 val.min_tens = t->tm_min / 10; 119 val.min_tens = t->tm_min / 10;
119 hour = t->tm_hour; 120 hour = t->tm_hour;
120 if (!hr24) { 121 if (!hr24) {
121 if (hour > 11) 122 if (hour > 11)
122 hour += 20 - 12; 123 hour += 20 - 12;
123 if (hour == 0 || hour == 20) 124 if (hour == 0 || hour == 20)
124 hour += 12; 125 hour += 12;
125 } 126 }
126 val.hr_ones = hour % 10; 127 val.hr_ones = hour % 10;
127 val.hr_tens = hour / 10; 128 val.hr_tens = hour / 10;
128 val.day_ones = t->tm_mday % 10; 129 val.day_ones = t->tm_mday % 10;
129 val.day_tens = t->tm_mday / 10; 130 val.day_tens = t->tm_mday / 10;
130 val.mon_ones = (t->tm_mon+1) % 10; 131 val.mon_ones = (t->tm_mon+1) % 10;
131 val.mon_tens = (t->tm_mon+1) / 10; 132 val.mon_tens = (t->tm_mon+1) / 10;
132 year = t->tm_year - 80; 133 year = t->tm_year - 80;
133 val.year_ones = year % 10; 134 val.year_ones = year % 10;
134 val.year_tens = year / 10; 135 val.year_tens = year / 10;
135 val.weekday = t->tm_wday; 136 val.weekday = t->tm_wday;
136 mste_write(&val); 137 mste_write(&val);
137 mste_rtc.mode=(mste_rtc.mode | 1); 138 mste_rtc.mode=(mste_rtc.mode | 1);
138 val.year_ones = (year % 4); /* leap year register */ 139 val.year_ones = (year % 4); /* leap year register */
139 mste_rtc.mode=(mste_rtc.mode & ~1); 140 mste_rtc.mode=(mste_rtc.mode & ~1);
140 } 141 }
141 else { 142 else {
142 mste_read(&val); 143 mste_read(&val);
143 t->tm_sec = val.sec_ones + val.sec_tens * 10; 144 t->tm_sec = val.sec_ones + val.sec_tens * 10;
144 t->tm_min = val.min_ones + val.min_tens * 10; 145 t->tm_min = val.min_ones + val.min_tens * 10;
145 hour = val.hr_ones + val.hr_tens * 10; 146 hour = val.hr_ones + val.hr_tens * 10;
146 if (!hr24) { 147 if (!hr24) {
147 if (hour == 12 || hour == 12 + 20) 148 if (hour == 12 || hour == 12 + 20)
148 hour -= 12; 149 hour -= 12;
149 if (hour >= 20) 150 if (hour >= 20)
150 hour += 12 - 20; 151 hour += 12 - 20;
151 } 152 }
152 t->tm_hour = hour; 153 t->tm_hour = hour;
153 t->tm_mday = val.day_ones + val.day_tens * 10; 154 t->tm_mday = val.day_ones + val.day_tens * 10;
154 t->tm_mon = val.mon_ones + val.mon_tens * 10 - 1; 155 t->tm_mon = val.mon_ones + val.mon_tens * 10 - 1;
155 t->tm_year = val.year_ones + val.year_tens * 10 + 80; 156 t->tm_year = val.year_ones + val.year_tens * 10 + 80;
156 t->tm_wday = val.weekday; 157 t->tm_wday = val.weekday;
157 } 158 }
158 return 0; 159 return 0;
159 } 160 }
160 161
161 int atari_tt_hwclk( int op, struct rtc_time *t ) 162 int atari_tt_hwclk( int op, struct rtc_time *t )
162 { 163 {
163 int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0; 164 int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
164 unsigned long flags; 165 unsigned long flags;
165 unsigned char ctrl; 166 unsigned char ctrl;
166 int pm = 0; 167 int pm = 0;
167 168
168 ctrl = RTC_READ(RTC_CONTROL); /* control registers are 169 ctrl = RTC_READ(RTC_CONTROL); /* control registers are
169 * independent from the UIP */ 170 * independent from the UIP */
170 171
171 if (op) { 172 if (op) {
172 /* write: prepare values */ 173 /* write: prepare values */
173 174
174 sec = t->tm_sec; 175 sec = t->tm_sec;
175 min = t->tm_min; 176 min = t->tm_min;
176 hour = t->tm_hour; 177 hour = t->tm_hour;
177 day = t->tm_mday; 178 day = t->tm_mday;
178 mon = t->tm_mon + 1; 179 mon = t->tm_mon + 1;
179 year = t->tm_year - atari_rtc_year_offset; 180 year = t->tm_year - atari_rtc_year_offset;
180 wday = t->tm_wday + (t->tm_wday >= 0); 181 wday = t->tm_wday + (t->tm_wday >= 0);
181 182
182 if (!(ctrl & RTC_24H)) { 183 if (!(ctrl & RTC_24H)) {
183 if (hour > 11) { 184 if (hour > 11) {
184 pm = 0x80; 185 pm = 0x80;
185 if (hour != 12) 186 if (hour != 12)
186 hour -= 12; 187 hour -= 12;
187 } 188 }
188 else if (hour == 0) 189 else if (hour == 0)
189 hour = 12; 190 hour = 12;
190 } 191 }
191 192
192 if (!(ctrl & RTC_DM_BINARY)) { 193 if (!(ctrl & RTC_DM_BINARY)) {
193 BIN_TO_BCD(sec); 194 BIN_TO_BCD(sec);
194 BIN_TO_BCD(min); 195 BIN_TO_BCD(min);
195 BIN_TO_BCD(hour); 196 BIN_TO_BCD(hour);
196 BIN_TO_BCD(day); 197 BIN_TO_BCD(day);
197 BIN_TO_BCD(mon); 198 BIN_TO_BCD(mon);
198 BIN_TO_BCD(year); 199 BIN_TO_BCD(year);
199 if (wday >= 0) BIN_TO_BCD(wday); 200 if (wday >= 0) BIN_TO_BCD(wday);
200 } 201 }
201 } 202 }
202 203
203 /* Reading/writing the clock registers is a bit critical due to 204 /* Reading/writing the clock registers is a bit critical due to
204 * the regular update cycle of the RTC. While an update is in 205 * the regular update cycle of the RTC. While an update is in
205 * progress, registers 0..9 shouldn't be touched. 206 * progress, registers 0..9 shouldn't be touched.
206 * The problem is solved like that: If an update is currently in 207 * The problem is solved like that: If an update is currently in
207 * progress (the UIP bit is set), the process sleeps for a while 208 * progress (the UIP bit is set), the process sleeps for a while
208 * (50ms). This really should be enough, since the update cycle 209 * (50ms). This really should be enough, since the update cycle
209 * normally needs 2 ms. 210 * normally needs 2 ms.
210 * If the UIP bit reads as 0, we have at least 244 usecs until the 211 * If the UIP bit reads as 0, we have at least 244 usecs until the
211 * update starts. This should be enough... But to be sure, 212 * update starts. This should be enough... But to be sure,
212 * additionally the RTC_SET bit is set to prevent an update cycle. 213 * additionally the RTC_SET bit is set to prevent an update cycle.
213 */ 214 */
214 215
215 while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) 216 while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
216 schedule_timeout_interruptible(HWCLK_POLL_INTERVAL); 217 if (in_atomic() || irqs_disabled())
218 mdelay(1);
219 else
220 schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
221 }
217 222
218 local_irq_save(flags); 223 local_irq_save(flags);
219 RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET ); 224 RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
220 if (!op) { 225 if (!op) {
221 sec = RTC_READ( RTC_SECONDS ); 226 sec = RTC_READ( RTC_SECONDS );
222 min = RTC_READ( RTC_MINUTES ); 227 min = RTC_READ( RTC_MINUTES );
223 hour = RTC_READ( RTC_HOURS ); 228 hour = RTC_READ( RTC_HOURS );
224 day = RTC_READ( RTC_DAY_OF_MONTH ); 229 day = RTC_READ( RTC_DAY_OF_MONTH );
225 mon = RTC_READ( RTC_MONTH ); 230 mon = RTC_READ( RTC_MONTH );
226 year = RTC_READ( RTC_YEAR ); 231 year = RTC_READ( RTC_YEAR );
227 wday = RTC_READ( RTC_DAY_OF_WEEK ); 232 wday = RTC_READ( RTC_DAY_OF_WEEK );
228 } 233 }
229 else { 234 else {
230 RTC_WRITE( RTC_SECONDS, sec ); 235 RTC_WRITE( RTC_SECONDS, sec );
231 RTC_WRITE( RTC_MINUTES, min ); 236 RTC_WRITE( RTC_MINUTES, min );
232 RTC_WRITE( RTC_HOURS, hour + pm); 237 RTC_WRITE( RTC_HOURS, hour + pm);
233 RTC_WRITE( RTC_DAY_OF_MONTH, day ); 238 RTC_WRITE( RTC_DAY_OF_MONTH, day );
234 RTC_WRITE( RTC_MONTH, mon ); 239 RTC_WRITE( RTC_MONTH, mon );
235 RTC_WRITE( RTC_YEAR, year ); 240 RTC_WRITE( RTC_YEAR, year );
236 if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday ); 241 if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
237 } 242 }
238 RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET ); 243 RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
239 local_irq_restore(flags); 244 local_irq_restore(flags);
240 245
241 if (!op) { 246 if (!op) {
242 /* read: adjust values */ 247 /* read: adjust values */
243 248
244 if (hour & 0x80) { 249 if (hour & 0x80) {
245 hour &= ~0x80; 250 hour &= ~0x80;
246 pm = 1; 251 pm = 1;
247 } 252 }
248 253
249 if (!(ctrl & RTC_DM_BINARY)) { 254 if (!(ctrl & RTC_DM_BINARY)) {
250 BCD_TO_BIN(sec); 255 BCD_TO_BIN(sec);
251 BCD_TO_BIN(min); 256 BCD_TO_BIN(min);
252 BCD_TO_BIN(hour); 257 BCD_TO_BIN(hour);
253 BCD_TO_BIN(day); 258 BCD_TO_BIN(day);
254 BCD_TO_BIN(mon); 259 BCD_TO_BIN(mon);
255 BCD_TO_BIN(year); 260 BCD_TO_BIN(year);
256 BCD_TO_BIN(wday); 261 BCD_TO_BIN(wday);
257 } 262 }
258 263
259 if (!(ctrl & RTC_24H)) { 264 if (!(ctrl & RTC_24H)) {
260 if (!pm && hour == 12) 265 if (!pm && hour == 12)
261 hour = 0; 266 hour = 0;
262 else if (pm && hour != 12) 267 else if (pm && hour != 12)
263 hour += 12; 268 hour += 12;
264 } 269 }
265 270
266 t->tm_sec = sec; 271 t->tm_sec = sec;
267 t->tm_min = min; 272 t->tm_min = min;
268 t->tm_hour = hour; 273 t->tm_hour = hour;
269 t->tm_mday = day; 274 t->tm_mday = day;
270 t->tm_mon = mon - 1; 275 t->tm_mon = mon - 1;
271 t->tm_year = year + atari_rtc_year_offset; 276 t->tm_year = year + atari_rtc_year_offset;
272 t->tm_wday = wday - 1; 277 t->tm_wday = wday - 1;
273 } 278 }
274 279
275 return( 0 ); 280 return( 0 );
276 } 281 }
277 282
278 283
279 int atari_mste_set_clock_mmss (unsigned long nowtime) 284 int atari_mste_set_clock_mmss (unsigned long nowtime)
280 { 285 {
281 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; 286 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
282 struct MSTE_RTC val; 287 struct MSTE_RTC val;
283 unsigned char rtc_minutes; 288 unsigned char rtc_minutes;
284 289
285 mste_read(&val); 290 mste_read(&val);
286 rtc_minutes= val.min_ones + val.min_tens * 10; 291 rtc_minutes= val.min_ones + val.min_tens * 10;
287 if ((rtc_minutes < real_minutes 292 if ((rtc_minutes < real_minutes
288 ? real_minutes - rtc_minutes 293 ? real_minutes - rtc_minutes
289 : rtc_minutes - real_minutes) < 30) 294 : rtc_minutes - real_minutes) < 30)
290 { 295 {
291 val.sec_ones = real_seconds % 10; 296 val.sec_ones = real_seconds % 10;
292 val.sec_tens = real_seconds / 10; 297 val.sec_tens = real_seconds / 10;
293 val.min_ones = real_minutes % 10; 298 val.min_ones = real_minutes % 10;
294 val.min_tens = real_minutes / 10; 299 val.min_tens = real_minutes / 10;
295 mste_write(&val); 300 mste_write(&val);
296 } 301 }
297 else 302 else
298 return -1; 303 return -1;
299 return 0; 304 return 0;
300 } 305 }
301 306
302 int atari_tt_set_clock_mmss (unsigned long nowtime) 307 int atari_tt_set_clock_mmss (unsigned long nowtime)
303 { 308 {
304 int retval = 0; 309 int retval = 0;
305 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; 310 short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
306 unsigned char save_control, save_freq_select, rtc_minutes; 311 unsigned char save_control, save_freq_select, rtc_minutes;
307 312
308 save_control = RTC_READ (RTC_CONTROL); /* tell the clock it's being set */ 313 save_control = RTC_READ (RTC_CONTROL); /* tell the clock it's being set */
309 RTC_WRITE (RTC_CONTROL, save_control | RTC_SET); 314 RTC_WRITE (RTC_CONTROL, save_control | RTC_SET);
310 315
311 save_freq_select = RTC_READ (RTC_FREQ_SELECT); /* stop and reset prescaler */ 316 save_freq_select = RTC_READ (RTC_FREQ_SELECT); /* stop and reset prescaler */
312 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select | RTC_DIV_RESET2); 317 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select | RTC_DIV_RESET2);
313 318
314 rtc_minutes = RTC_READ (RTC_MINUTES); 319 rtc_minutes = RTC_READ (RTC_MINUTES);
315 if (!(save_control & RTC_DM_BINARY)) 320 if (!(save_control & RTC_DM_BINARY))
316 BCD_TO_BIN (rtc_minutes); 321 BCD_TO_BIN (rtc_minutes);
317 322
318 /* Since we're only adjusting minutes and seconds, don't interfere 323 /* Since we're only adjusting minutes and seconds, don't interfere
319 with hour overflow. This avoids messing with unknown time zones 324 with hour overflow. This avoids messing with unknown time zones
320 but requires your RTC not to be off by more than 30 minutes. */ 325 but requires your RTC not to be off by more than 30 minutes. */
321 if ((rtc_minutes < real_minutes 326 if ((rtc_minutes < real_minutes
322 ? real_minutes - rtc_minutes 327 ? real_minutes - rtc_minutes
323 : rtc_minutes - real_minutes) < 30) 328 : rtc_minutes - real_minutes) < 30)
324 { 329 {
325 if (!(save_control & RTC_DM_BINARY)) 330 if (!(save_control & RTC_DM_BINARY))
326 { 331 {
327 BIN_TO_BCD (real_seconds); 332 BIN_TO_BCD (real_seconds);
328 BIN_TO_BCD (real_minutes); 333 BIN_TO_BCD (real_minutes);
329 } 334 }
330 RTC_WRITE (RTC_SECONDS, real_seconds); 335 RTC_WRITE (RTC_SECONDS, real_seconds);
331 RTC_WRITE (RTC_MINUTES, real_minutes); 336 RTC_WRITE (RTC_MINUTES, real_minutes);
332 } 337 }
333 else 338 else
334 retval = -1; 339 retval = -1;
335 340
336 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select); 341 RTC_WRITE (RTC_FREQ_SELECT, save_freq_select);
337 RTC_WRITE (RTC_CONTROL, save_control); 342 RTC_WRITE (RTC_CONTROL, save_control);
338 return retval; 343 return retval;
339 } 344 }
340 345
341 /* 346 /*
342 * Local variables: 347 * Local variables:
343 * c-indent-level: 4 348 * c-indent-level: 4
344 * tab-width: 8 349 * tab-width: 8
345 * End: 350 * End:
346 */ 351 */
347 352
arch/m68k/kernel/ints.c
1 /* 1 /*
2 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code 2 * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code
3 * 3 *
4 * This file is subject to the terms and conditions of the GNU General Public 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 5 * License. See the file COPYING in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * 07/03/96: Timer initialization, and thus mach_sched_init(), 8 * 07/03/96: Timer initialization, and thus mach_sched_init(),
9 * removed from request_irq() and moved to init_time(). 9 * removed from request_irq() and moved to init_time().
10 * We should therefore consider renaming our add_isr() and 10 * We should therefore consider renaming our add_isr() and
11 * remove_isr() to request_irq() and free_irq() 11 * remove_isr() to request_irq() and free_irq()
12 * respectively, so they are compliant with the other 12 * respectively, so they are compliant with the other
13 * architectures. /Jes 13 * architectures. /Jes
14 * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls. 14 * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
15 * Removed irq list support, if any machine needs an irq server 15 * Removed irq list support, if any machine needs an irq server
16 * it must implement this itself (as it's already done), instead 16 * it must implement this itself (as it's already done), instead
17 * only default handler are used with mach_default_handler. 17 * only default handler are used with mach_default_handler.
18 * request_irq got some flags different from other architectures: 18 * request_irq got some flags different from other architectures:
19 * - IRQ_FLG_REPLACE : Replace an existing handler (the default one 19 * - IRQ_FLG_REPLACE : Replace an existing handler (the default one
20 * can be replaced without this flag) 20 * can be replaced without this flag)
21 * - IRQ_FLG_LOCK : handler can't be replaced 21 * - IRQ_FLG_LOCK : handler can't be replaced
22 * There are other machine depending flags, see there 22 * There are other machine depending flags, see there
23 * If you want to replace a default handler you should know what 23 * If you want to replace a default handler you should know what
24 * you're doing, since it might handle different other irq sources 24 * you're doing, since it might handle different other irq sources
25 * which must be served /Roman Zippel 25 * which must be served /Roman Zippel
26 */ 26 */
27 27
28 #include <linux/module.h> 28 #include <linux/module.h>
29 #include <linux/types.h> 29 #include <linux/types.h>
30 #include <linux/sched.h> 30 #include <linux/sched.h>
31 #include <linux/kernel_stat.h> 31 #include <linux/kernel_stat.h>
32 #include <linux/errno.h> 32 #include <linux/errno.h>
33 #include <linux/init.h> 33 #include <linux/init.h>
34 34
35 #include <asm/setup.h> 35 #include <asm/setup.h>
36 #include <asm/system.h> 36 #include <asm/system.h>
37 #include <asm/irq.h> 37 #include <asm/irq.h>
38 #include <asm/traps.h> 38 #include <asm/traps.h>
39 #include <asm/page.h> 39 #include <asm/page.h>
40 #include <asm/machdep.h> 40 #include <asm/machdep.h>
41 #include <asm/cacheflush.h> 41 #include <asm/cacheflush.h>
42 #include <asm/irq_regs.h> 42 #include <asm/irq_regs.h>
43 43
44 #ifdef CONFIG_Q40 44 #ifdef CONFIG_Q40
45 #include <asm/q40ints.h> 45 #include <asm/q40ints.h>
46 #endif 46 #endif
47 47
48 extern u32 auto_irqhandler_fixup[]; 48 extern u32 auto_irqhandler_fixup[];
49 extern u32 user_irqhandler_fixup[]; 49 extern u32 user_irqhandler_fixup[];
50 extern u16 user_irqvec_fixup[]; 50 extern u16 user_irqvec_fixup[];
51 51
52 /* table for system interrupt handlers */ 52 /* table for system interrupt handlers */
53 static struct irq_node *irq_list[NR_IRQS]; 53 static struct irq_node *irq_list[NR_IRQS];
54 static struct irq_controller *irq_controller[NR_IRQS]; 54 static struct irq_controller *irq_controller[NR_IRQS];
55 static int irq_depth[NR_IRQS]; 55 static int irq_depth[NR_IRQS];
56 56
57 static int m68k_first_user_vec; 57 static int m68k_first_user_vec;
58 58
59 static struct irq_controller auto_irq_controller = { 59 static struct irq_controller auto_irq_controller = {
60 .name = "auto", 60 .name = "auto",
61 .lock = SPIN_LOCK_UNLOCKED, 61 .lock = SPIN_LOCK_UNLOCKED,
62 .startup = m68k_irq_startup, 62 .startup = m68k_irq_startup,
63 .shutdown = m68k_irq_shutdown, 63 .shutdown = m68k_irq_shutdown,
64 }; 64 };
65 65
66 static struct irq_controller user_irq_controller = { 66 static struct irq_controller user_irq_controller = {
67 .name = "user", 67 .name = "user",
68 .lock = SPIN_LOCK_UNLOCKED, 68 .lock = SPIN_LOCK_UNLOCKED,
69 .startup = m68k_irq_startup, 69 .startup = m68k_irq_startup,
70 .shutdown = m68k_irq_shutdown, 70 .shutdown = m68k_irq_shutdown,
71 }; 71 };
72 72
73 #define NUM_IRQ_NODES 100 73 #define NUM_IRQ_NODES 100
74 static irq_node_t nodes[NUM_IRQ_NODES]; 74 static irq_node_t nodes[NUM_IRQ_NODES];
75 75
76 /* 76 /*
77 * void init_IRQ(void) 77 * void init_IRQ(void)
78 * 78 *
79 * Parameters: None 79 * Parameters: None
80 * 80 *
81 * Returns: Nothing 81 * Returns: Nothing
82 * 82 *
83 * This function should be called during kernel startup to initialize 83 * This function should be called during kernel startup to initialize
84 * the IRQ handling routines. 84 * the IRQ handling routines.
85 */ 85 */
86 86
87 void __init init_IRQ(void) 87 void __init init_IRQ(void)
88 { 88 {
89 int i; 89 int i;
90 90
91 /* assembly irq entry code relies on this... */ 91 /* assembly irq entry code relies on this... */
92 if (HARDIRQ_MASK != 0x00ff0000) { 92 if (HARDIRQ_MASK != 0x00ff0000) {
93 extern void hardirq_mask_is_broken(void); 93 extern void hardirq_mask_is_broken(void);
94 hardirq_mask_is_broken(); 94 hardirq_mask_is_broken();
95 } 95 }
96 96
97 for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) 97 for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
98 irq_controller[i] = &auto_irq_controller; 98 irq_controller[i] = &auto_irq_controller;
99 99
100 mach_init_IRQ(); 100 mach_init_IRQ();
101 } 101 }
102 102
103 /** 103 /**
104 * m68k_setup_auto_interrupt 104 * m68k_setup_auto_interrupt
105 * @handler: called from auto vector interrupts 105 * @handler: called from auto vector interrupts
106 * 106 *
107 * setup the handler to be called from auto vector interrupts instead of the 107 * setup the handler to be called from auto vector interrupts instead of the
108 * standard __m68k_handle_int(), it will be called with irq numbers in the range 108 * standard __m68k_handle_int(), it will be called with irq numbers in the range
109 * from IRQ_AUTO_1 - IRQ_AUTO_7. 109 * from IRQ_AUTO_1 - IRQ_AUTO_7.
110 */ 110 */
111 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) 111 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
112 { 112 {
113 if (handler) 113 if (handler)
114 *auto_irqhandler_fixup = (u32)handler; 114 *auto_irqhandler_fixup = (u32)handler;
115 flush_icache(); 115 flush_icache();
116 } 116 }
117 117
118 /** 118 /**
119 * m68k_setup_user_interrupt 119 * m68k_setup_user_interrupt
120 * @vec: first user vector interrupt to handle 120 * @vec: first user vector interrupt to handle
121 * @cnt: number of active user vector interrupts 121 * @cnt: number of active user vector interrupts
122 * @handler: called from user vector interrupts 122 * @handler: called from user vector interrupts
123 * 123 *
124 * setup user vector interrupts, this includes activating the specified range 124 * setup user vector interrupts, this includes activating the specified range
125 * of interrupts, only then these interrupts can be requested (note: this is 125 * of interrupts, only then these interrupts can be requested (note: this is
126 * different from auto vector interrupts). An optional handler can be installed 126 * different from auto vector interrupts). An optional handler can be installed
127 * to be called instead of the default __m68k_handle_int(), it will be called 127 * to be called instead of the default __m68k_handle_int(), it will be called
128 * with irq numbers starting from IRQ_USER. 128 * with irq numbers starting from IRQ_USER.
129 */ 129 */
130 void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, 130 void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
131 void (*handler)(unsigned int, struct pt_regs *)) 131 void (*handler)(unsigned int, struct pt_regs *))
132 { 132 {
133 int i; 133 int i;
134 134
135 BUG_ON(IRQ_USER + cnt >= NR_IRQS);
135 m68k_first_user_vec = vec; 136 m68k_first_user_vec = vec;
136 for (i = 0; i < cnt; i++) 137 for (i = 0; i < cnt; i++)
137 irq_controller[IRQ_USER + i] = &user_irq_controller; 138 irq_controller[IRQ_USER + i] = &user_irq_controller;
138 *user_irqvec_fixup = vec - IRQ_USER; 139 *user_irqvec_fixup = vec - IRQ_USER;
139 if (handler) 140 if (handler)
140 *user_irqhandler_fixup = (u32)handler; 141 *user_irqhandler_fixup = (u32)handler;
141 flush_icache(); 142 flush_icache();
142 } 143 }
143 144
144 /** 145 /**
145 * m68k_setup_irq_controller 146 * m68k_setup_irq_controller
146 * @contr: irq controller which controls specified irq 147 * @contr: irq controller which controls specified irq
147 * @irq: first irq to be managed by the controller 148 * @irq: first irq to be managed by the controller
148 * 149 *
149 * Change the controller for the specified range of irq, which will be used to 150 * Change the controller for the specified range of irq, which will be used to
150 * manage these irq. auto/user irq already have a default controller, which can 151 * manage these irq. auto/user irq already have a default controller, which can
151 * be changed as well, but the controller probably should use m68k_irq_startup/ 152 * be changed as well, but the controller probably should use m68k_irq_startup/
152 * m68k_irq_shutdown. 153 * m68k_irq_shutdown.
153 */ 154 */
154 void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, 155 void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
155 unsigned int cnt) 156 unsigned int cnt)
156 { 157 {
157 int i; 158 int i;
158 159
159 for (i = 0; i < cnt; i++) 160 for (i = 0; i < cnt; i++)
160 irq_controller[irq + i] = contr; 161 irq_controller[irq + i] = contr;
161 } 162 }
162 163
163 irq_node_t *new_irq_node(void) 164 irq_node_t *new_irq_node(void)
164 { 165 {
165 irq_node_t *node; 166 irq_node_t *node;
166 short i; 167 short i;
167 168
168 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { 169 for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
169 if (!node->handler) { 170 if (!node->handler) {
170 memset(node, 0, sizeof(*node)); 171 memset(node, 0, sizeof(*node));
171 return node; 172 return node;
172 } 173 }
173 } 174 }
174 175
175 printk ("new_irq_node: out of nodes\n"); 176 printk ("new_irq_node: out of nodes\n");
176 return NULL; 177 return NULL;
177 } 178 }
178 179
179 int setup_irq(unsigned int irq, struct irq_node *node) 180 int setup_irq(unsigned int irq, struct irq_node *node)
180 { 181 {
181 struct irq_controller *contr; 182 struct irq_controller *contr;
182 struct irq_node **prev; 183 struct irq_node **prev;
183 unsigned long flags; 184 unsigned long flags;
184 185
185 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 186 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
186 printk("%s: Incorrect IRQ %d from %s\n", 187 printk("%s: Incorrect IRQ %d from %s\n",
187 __FUNCTION__, irq, node->devname); 188 __FUNCTION__, irq, node->devname);
188 return -ENXIO; 189 return -ENXIO;
189 } 190 }
190 191
191 spin_lock_irqsave(&contr->lock, flags); 192 spin_lock_irqsave(&contr->lock, flags);
192 193
193 prev = irq_list + irq; 194 prev = irq_list + irq;
194 if (*prev) { 195 if (*prev) {
195 /* Can't share interrupts unless both agree to */ 196 /* Can't share interrupts unless both agree to */
196 if (!((*prev)->flags & node->flags & IRQF_SHARED)) { 197 if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
197 spin_unlock_irqrestore(&contr->lock, flags); 198 spin_unlock_irqrestore(&contr->lock, flags);
198 return -EBUSY; 199 return -EBUSY;
199 } 200 }
200 while (*prev) 201 while (*prev)
201 prev = &(*prev)->next; 202 prev = &(*prev)->next;
202 } 203 }
203 204
204 if (!irq_list[irq]) { 205 if (!irq_list[irq]) {
205 if (contr->startup) 206 if (contr->startup)
206 contr->startup(irq); 207 contr->startup(irq);
207 else 208 else
208 contr->enable(irq); 209 contr->enable(irq);
209 } 210 }
210 node->next = NULL; 211 node->next = NULL;
211 *prev = node; 212 *prev = node;
212 213
213 spin_unlock_irqrestore(&contr->lock, flags); 214 spin_unlock_irqrestore(&contr->lock, flags);
214 215
215 return 0; 216 return 0;
216 } 217 }
217 218
218 int request_irq(unsigned int irq, 219 int request_irq(unsigned int irq,
219 irq_handler_t handler, 220 irq_handler_t handler,
220 unsigned long flags, const char *devname, void *dev_id) 221 unsigned long flags, const char *devname, void *dev_id)
221 { 222 {
222 struct irq_node *node; 223 struct irq_node *node;
223 int res; 224 int res;
224 225
225 node = new_irq_node(); 226 node = new_irq_node();
226 if (!node) 227 if (!node)
227 return -ENOMEM; 228 return -ENOMEM;
228 229
229 node->handler = handler; 230 node->handler = handler;
230 node->flags = flags; 231 node->flags = flags;
231 node->dev_id = dev_id; 232 node->dev_id = dev_id;
232 node->devname = devname; 233 node->devname = devname;
233 234
234 res = setup_irq(irq, node); 235 res = setup_irq(irq, node);
235 if (res) 236 if (res)
236 node->handler = NULL; 237 node->handler = NULL;
237 238
238 return res; 239 return res;
239 } 240 }
240 241
241 EXPORT_SYMBOL(request_irq); 242 EXPORT_SYMBOL(request_irq);
242 243
243 void free_irq(unsigned int irq, void *dev_id) 244 void free_irq(unsigned int irq, void *dev_id)
244 { 245 {
245 struct irq_controller *contr; 246 struct irq_controller *contr;
246 struct irq_node **p, *node; 247 struct irq_node **p, *node;
247 unsigned long flags; 248 unsigned long flags;
248 249
249 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 250 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
250 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); 251 printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
251 return; 252 return;
252 } 253 }
253 254
254 spin_lock_irqsave(&contr->lock, flags); 255 spin_lock_irqsave(&contr->lock, flags);
255 256
256 p = irq_list + irq; 257 p = irq_list + irq;
257 while ((node = *p)) { 258 while ((node = *p)) {
258 if (node->dev_id == dev_id) 259 if (node->dev_id == dev_id)
259 break; 260 break;
260 p = &node->next; 261 p = &node->next;
261 } 262 }
262 263
263 if (node) { 264 if (node) {
264 *p = node->next; 265 *p = node->next;
265 node->handler = NULL; 266 node->handler = NULL;
266 } else 267 } else
267 printk("%s: Removing probably wrong IRQ %d\n", 268 printk("%s: Removing probably wrong IRQ %d\n",
268 __FUNCTION__, irq); 269 __FUNCTION__, irq);
269 270
270 if (!irq_list[irq]) { 271 if (!irq_list[irq]) {
271 if (contr->shutdown) 272 if (contr->shutdown)
272 contr->shutdown(irq); 273 contr->shutdown(irq);
273 else 274 else
274 contr->disable(irq); 275 contr->disable(irq);
275 } 276 }
276 277
277 spin_unlock_irqrestore(&contr->lock, flags); 278 spin_unlock_irqrestore(&contr->lock, flags);
278 } 279 }
279 280
280 EXPORT_SYMBOL(free_irq); 281 EXPORT_SYMBOL(free_irq);
281 282
282 void enable_irq(unsigned int irq) 283 void enable_irq(unsigned int irq)
283 { 284 {
284 struct irq_controller *contr; 285 struct irq_controller *contr;
285 unsigned long flags; 286 unsigned long flags;
286 287
287 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 288 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
288 printk("%s: Incorrect IRQ %d\n", 289 printk("%s: Incorrect IRQ %d\n",
289 __FUNCTION__, irq); 290 __FUNCTION__, irq);
290 return; 291 return;
291 } 292 }
292 293
293 spin_lock_irqsave(&contr->lock, flags); 294 spin_lock_irqsave(&contr->lock, flags);
294 if (irq_depth[irq]) { 295 if (irq_depth[irq]) {
295 if (!--irq_depth[irq]) { 296 if (!--irq_depth[irq]) {
296 if (contr->enable) 297 if (contr->enable)
297 contr->enable(irq); 298 contr->enable(irq);
298 } 299 }
299 } else 300 } else
300 WARN_ON(1); 301 WARN_ON(1);
301 spin_unlock_irqrestore(&contr->lock, flags); 302 spin_unlock_irqrestore(&contr->lock, flags);
302 } 303 }
303 304
304 EXPORT_SYMBOL(enable_irq); 305 EXPORT_SYMBOL(enable_irq);
305 306
306 void disable_irq(unsigned int irq) 307 void disable_irq(unsigned int irq)
307 { 308 {
308 struct irq_controller *contr; 309 struct irq_controller *contr;
309 unsigned long flags; 310 unsigned long flags;
310 311
311 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { 312 if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
312 printk("%s: Incorrect IRQ %d\n", 313 printk("%s: Incorrect IRQ %d\n",
313 __FUNCTION__, irq); 314 __FUNCTION__, irq);
314 return; 315 return;
315 } 316 }
316 317
317 spin_lock_irqsave(&contr->lock, flags); 318 spin_lock_irqsave(&contr->lock, flags);
318 if (!irq_depth[irq]++) { 319 if (!irq_depth[irq]++) {
319 if (contr->disable) 320 if (contr->disable)
320 contr->disable(irq); 321 contr->disable(irq);
321 } 322 }
322 spin_unlock_irqrestore(&contr->lock, flags); 323 spin_unlock_irqrestore(&contr->lock, flags);
323 } 324 }
324 325
325 EXPORT_SYMBOL(disable_irq); 326 EXPORT_SYMBOL(disable_irq);
326 327
327 int m68k_irq_startup(unsigned int irq) 328 int m68k_irq_startup(unsigned int irq)
328 { 329 {
329 if (irq <= IRQ_AUTO_7) 330 if (irq <= IRQ_AUTO_7)
330 vectors[VEC_SPUR + irq] = auto_inthandler; 331 vectors[VEC_SPUR + irq] = auto_inthandler;
331 else 332 else
332 vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler; 333 vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler;
333 return 0; 334 return 0;
334 } 335 }
335 336
336 void m68k_irq_shutdown(unsigned int irq) 337 void m68k_irq_shutdown(unsigned int irq)
337 { 338 {
338 if (irq <= IRQ_AUTO_7) 339 if (irq <= IRQ_AUTO_7)
339 vectors[VEC_SPUR + irq] = bad_inthandler; 340 vectors[VEC_SPUR + irq] = bad_inthandler;
340 else 341 else
341 vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; 342 vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
342 } 343 }
343 344
344 345
345 /* 346 /*
346 * Do we need these probe functions on the m68k? 347 * Do we need these probe functions on the m68k?
347 * 348 *
348 * ... may be useful with ISA devices 349 * ... may be useful with ISA devices
349 */ 350 */
350 unsigned long probe_irq_on (void) 351 unsigned long probe_irq_on (void)
351 { 352 {
352 #ifdef CONFIG_Q40 353 #ifdef CONFIG_Q40
353 if (MACH_IS_Q40) 354 if (MACH_IS_Q40)
354 return q40_probe_irq_on(); 355 return q40_probe_irq_on();
355 #endif 356 #endif
356 return 0; 357 return 0;
357 } 358 }
358 359
359 EXPORT_SYMBOL(probe_irq_on); 360 EXPORT_SYMBOL(probe_irq_on);
360 361
361 int probe_irq_off (unsigned long irqs) 362 int probe_irq_off (unsigned long irqs)
362 { 363 {
363 #ifdef CONFIG_Q40 364 #ifdef CONFIG_Q40
364 if (MACH_IS_Q40) 365 if (MACH_IS_Q40)
365 return q40_probe_irq_off(irqs); 366 return q40_probe_irq_off(irqs);
366 #endif 367 #endif
367 return 0; 368 return 0;
368 } 369 }
369 370
370 EXPORT_SYMBOL(probe_irq_off); 371 EXPORT_SYMBOL(probe_irq_off);
371 372
372 unsigned int irq_canonicalize(unsigned int irq) 373 unsigned int irq_canonicalize(unsigned int irq)
373 { 374 {
374 #ifdef CONFIG_Q40 375 #ifdef CONFIG_Q40
375 if (MACH_IS_Q40 && irq == 11) 376 if (MACH_IS_Q40 && irq == 11)
376 irq = 10; 377 irq = 10;
377 #endif 378 #endif
378 return irq; 379 return irq;
379 } 380 }
380 381
381 EXPORT_SYMBOL(irq_canonicalize); 382 EXPORT_SYMBOL(irq_canonicalize);
382 383
383 asmlinkage void m68k_handle_int(unsigned int irq) 384 asmlinkage void m68k_handle_int(unsigned int irq)
384 { 385 {
385 struct irq_node *node; 386 struct irq_node *node;
386 kstat_cpu(0).irqs[irq]++; 387 kstat_cpu(0).irqs[irq]++;
387 node = irq_list[irq]; 388 node = irq_list[irq];
388 do { 389 do {
389 node->handler(irq, node->dev_id); 390 node->handler(irq, node->dev_id);
390 node = node->next; 391 node = node->next;
391 } while (node); 392 } while (node);
392 } 393 }
393 394
394 asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs) 395 asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
395 { 396 {
396 struct pt_regs *old_regs; 397 struct pt_regs *old_regs;
397 old_regs = set_irq_regs(regs); 398 old_regs = set_irq_regs(regs);
398 m68k_handle_int(irq); 399 m68k_handle_int(irq);
399 set_irq_regs(old_regs); 400 set_irq_regs(old_regs);
400 } 401 }
401 402
402 asmlinkage void handle_badint(struct pt_regs *regs) 403 asmlinkage void handle_badint(struct pt_regs *regs)
403 { 404 {
404 kstat_cpu(0).irqs[0]++; 405 kstat_cpu(0).irqs[0]++;
405 printk("unexpected interrupt from %u\n", regs->vector); 406 printk("unexpected interrupt from %u\n", regs->vector);
406 } 407 }
407 408
408 int show_interrupts(struct seq_file *p, void *v) 409 int show_interrupts(struct seq_file *p, void *v)
409 { 410 {
410 struct irq_controller *contr; 411 struct irq_controller *contr;
411 struct irq_node *node; 412 struct irq_node *node;
412 int i = *(loff_t *) v; 413 int i = *(loff_t *) v;
413 414
414 /* autovector interrupts */ 415 /* autovector interrupts */
415 if (irq_list[i]) { 416 if (irq_list[i]) {
416 contr = irq_controller[i]; 417 contr = irq_controller[i];
417 node = irq_list[i]; 418 node = irq_list[i];
418 seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); 419 seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
419 while ((node = node->next)) 420 while ((node = node->next))
420 seq_printf(p, ", %s", node->devname); 421 seq_printf(p, ", %s", node->devname);
421 seq_puts(p, "\n"); 422 seq_puts(p, "\n");
422 } 423 }
423 return 0; 424 return 0;
424 } 425 }
425 426
426 void init_irq_proc(void) 427 void init_irq_proc(void)
427 { 428 {
428 /* Insert /proc/irq driver here */ 429 /* Insert /proc/irq driver here */
429 } 430 }
430 431
431 432