0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/kernel_stat.h>
0016 #include <linux/seq_file.h>
0017 #include <linux/export.h>
0018
0019 #include <asm/cacheflush.h>
0020 #include <asm/cpudata.h>
0021 #include <asm/setup.h>
0022 #include <asm/pcic.h>
0023 #include <asm/leon.h>
0024
0025 #include "kernel.h"
0026 #include "irq.h"
0027
0028
0029 struct sparc_config sparc_config;
0030
0031 unsigned long arch_local_irq_save(void)
0032 {
0033 unsigned long retval;
0034 unsigned long tmp;
0035
0036 __asm__ __volatile__(
0037 "rd %%psr, %0\n\t"
0038 "or %0, %2, %1\n\t"
0039 "wr %1, 0, %%psr\n\t"
0040 "nop; nop; nop\n"
0041 : "=&r" (retval), "=r" (tmp)
0042 : "i" (PSR_PIL)
0043 : "memory");
0044
0045 return retval;
0046 }
0047 EXPORT_SYMBOL(arch_local_irq_save);
0048
0049 void arch_local_irq_enable(void)
0050 {
0051 unsigned long tmp;
0052
0053 __asm__ __volatile__(
0054 "rd %%psr, %0\n\t"
0055 "andn %0, %1, %0\n\t"
0056 "wr %0, 0, %%psr\n\t"
0057 "nop; nop; nop\n"
0058 : "=&r" (tmp)
0059 : "i" (PSR_PIL)
0060 : "memory");
0061 }
0062 EXPORT_SYMBOL(arch_local_irq_enable);
0063
0064 void arch_local_irq_restore(unsigned long old_psr)
0065 {
0066 unsigned long tmp;
0067
0068 __asm__ __volatile__(
0069 "rd %%psr, %0\n\t"
0070 "and %2, %1, %2\n\t"
0071 "andn %0, %1, %0\n\t"
0072 "wr %0, %2, %%psr\n\t"
0073 "nop; nop; nop\n"
0074 : "=&r" (tmp)
0075 : "i" (PSR_PIL), "r" (old_psr)
0076 : "memory");
0077 }
0078 EXPORT_SYMBOL(arch_local_irq_restore);
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 static struct irq_bucket irq_table[NR_IRQS];
0114
0115 static DEFINE_SPINLOCK(irq_table_lock);
0116
0117
0118 struct irq_bucket *irq_map[SUN4D_MAX_IRQ];
0119
0120 static DEFINE_SPINLOCK(irq_map_lock);
0121
0122
0123 unsigned int irq_alloc(unsigned int real_irq, unsigned int pil)
0124 {
0125 unsigned long flags;
0126 unsigned int i;
0127
0128 spin_lock_irqsave(&irq_table_lock, flags);
0129 for (i = 1; i < NR_IRQS; i++) {
0130 if (irq_table[i].real_irq == real_irq && irq_table[i].pil == pil)
0131 goto found;
0132 }
0133
0134 for (i = 1; i < NR_IRQS; i++) {
0135 if (!irq_table[i].irq)
0136 break;
0137 }
0138
0139 if (i < NR_IRQS) {
0140 irq_table[i].real_irq = real_irq;
0141 irq_table[i].irq = i;
0142 irq_table[i].pil = pil;
0143 } else {
0144 printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
0145 i = 0;
0146 }
0147 found:
0148 spin_unlock_irqrestore(&irq_table_lock, flags);
0149
0150 return i;
0151 }
0152
0153
0154
0155
0156
0157 void irq_link(unsigned int irq)
0158 {
0159 struct irq_bucket *p;
0160 unsigned long flags;
0161 unsigned int pil;
0162
0163 BUG_ON(irq >= NR_IRQS);
0164
0165 spin_lock_irqsave(&irq_map_lock, flags);
0166
0167 p = &irq_table[irq];
0168 pil = p->pil;
0169 BUG_ON(pil >= SUN4D_MAX_IRQ);
0170 p->next = irq_map[pil];
0171 irq_map[pil] = p;
0172
0173 spin_unlock_irqrestore(&irq_map_lock, flags);
0174 }
0175
0176 void irq_unlink(unsigned int irq)
0177 {
0178 struct irq_bucket *p, **pnext;
0179 unsigned long flags;
0180
0181 BUG_ON(irq >= NR_IRQS);
0182
0183 spin_lock_irqsave(&irq_map_lock, flags);
0184
0185 p = &irq_table[irq];
0186 BUG_ON(p->pil >= SUN4D_MAX_IRQ);
0187 pnext = &irq_map[p->pil];
0188 while (*pnext != p)
0189 pnext = &(*pnext)->next;
0190 *pnext = p->next;
0191
0192 spin_unlock_irqrestore(&irq_map_lock, flags);
0193 }
0194
0195
0196
0197 int arch_show_interrupts(struct seq_file *p, int prec)
0198 {
0199 int j;
0200
0201 #ifdef CONFIG_SMP
0202 seq_printf(p, "RES: ");
0203 for_each_online_cpu(j)
0204 seq_printf(p, "%10u ", cpu_data(j).irq_resched_count);
0205 seq_printf(p, " IPI rescheduling interrupts\n");
0206 seq_printf(p, "CAL: ");
0207 for_each_online_cpu(j)
0208 seq_printf(p, "%10u ", cpu_data(j).irq_call_count);
0209 seq_printf(p, " IPI function call interrupts\n");
0210 #endif
0211 seq_printf(p, "NMI: ");
0212 for_each_online_cpu(j)
0213 seq_printf(p, "%10u ", cpu_data(j).counter);
0214 seq_printf(p, " Non-maskable interrupts\n");
0215 return 0;
0216 }
0217
0218 void handler_irq(unsigned int pil, struct pt_regs *regs)
0219 {
0220 struct pt_regs *old_regs;
0221 struct irq_bucket *p;
0222
0223 BUG_ON(pil > 15);
0224 old_regs = set_irq_regs(regs);
0225 irq_enter();
0226
0227 p = irq_map[pil];
0228 while (p) {
0229 struct irq_bucket *next = p->next;
0230
0231 generic_handle_irq(p->irq);
0232 p = next;
0233 }
0234 irq_exit();
0235 set_irq_regs(old_regs);
0236 }
0237
0238 #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
0239 static unsigned int floppy_irq;
0240
0241 int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler)
0242 {
0243 unsigned int cpu_irq;
0244 int err;
0245
0246
0247 err = request_irq(irq, irq_handler, 0, "floppy", NULL);
0248 if (err)
0249 return -1;
0250
0251
0252 floppy_irq = irq;
0253
0254 cpu_irq = (irq & (NR_IRQS - 1));
0255
0256
0257 #define INSTANTIATE(table) \
0258 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_one = SPARC_RD_PSR_L0; \
0259 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two = \
0260 SPARC_BRANCH((unsigned long) floppy_hardint, \
0261 (unsigned long) &table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_two);\
0262 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_three = SPARC_RD_WIM_L3; \
0263 table[SP_TRAP_IRQ1+(cpu_irq-1)].inst_four = SPARC_NOP;
0264
0265 INSTANTIATE(sparc_ttable)
0266
0267 #if defined CONFIG_SMP
0268 if (sparc_cpu_model != sparc_leon) {
0269 struct tt_entry *trap_table;
0270
0271 trap_table = &trapbase_cpu1;
0272 INSTANTIATE(trap_table)
0273 trap_table = &trapbase_cpu2;
0274 INSTANTIATE(trap_table)
0275 trap_table = &trapbase_cpu3;
0276 INSTANTIATE(trap_table)
0277 }
0278 #endif
0279 #undef INSTANTIATE
0280
0281
0282
0283
0284
0285 flush_cache_all();
0286 return 0;
0287 }
0288 EXPORT_SYMBOL(sparc_floppy_request_irq);
0289
0290
0291
0292
0293
0294
0295
0296 volatile unsigned char *fdc_status;
0297 EXPORT_SYMBOL(fdc_status);
0298
0299 char *pdma_vaddr;
0300 EXPORT_SYMBOL(pdma_vaddr);
0301
0302 unsigned long pdma_size;
0303 EXPORT_SYMBOL(pdma_size);
0304
0305 volatile int doing_pdma;
0306 EXPORT_SYMBOL(doing_pdma);
0307
0308 char *pdma_base;
0309 EXPORT_SYMBOL(pdma_base);
0310
0311 unsigned long pdma_areasize;
0312 EXPORT_SYMBOL(pdma_areasize);
0313
0314
0315
0316
0317
0318
0319 void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
0320 {
0321 struct pt_regs *old_regs;
0322
0323 old_regs = set_irq_regs(regs);
0324 irq_enter();
0325 generic_handle_irq(floppy_irq);
0326 irq_exit();
0327 set_irq_regs(old_regs);
0328 }
0329 #endif
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339 void __init init_IRQ(void)
0340 {
0341 switch (sparc_cpu_model) {
0342 case sun4m:
0343 pcic_probe();
0344 if (pcic_present())
0345 sun4m_pci_init_IRQ();
0346 else
0347 sun4m_init_IRQ();
0348 break;
0349
0350 case sun4d:
0351 sun4d_init_IRQ();
0352 break;
0353
0354 case sparc_leon:
0355 leon_init_IRQ();
0356 break;
0357
0358 default:
0359 prom_printf("Cannot initialize IRQs on this Sun machine...");
0360 break;
0361 }
0362 }
0363