1/* 2 * linux/arch/alpha/kernel/sys_mikasa.c 3 * 4 * Copyright (C) 1995 David A Rusling 5 * Copyright (C) 1996 Jay A Estabrook 6 * Copyright (C) 1998, 1999 Richard Henderson 7 * 8 * Code supporting the MIKASA (AlphaServer 1000). 9 */ 10 11#include <linux/config.h> 12#include <linux/kernel.h> 13#include <linux/types.h> 14#include <linux/mm.h> 15#include <linux/sched.h> 16#include <linux/pci.h> 17#include <linux/init.h> 18 19#include <asm/ptrace.h> 20#include <asm/system.h> 21#include <asm/dma.h> 22#include <asm/irq.h> 23#include <asm/bitops.h> 24#include <asm/mmu_context.h> 25#include <asm/io.h> 26#include <asm/pgtable.h> 27#include <asm/core_apecs.h> 28#include <asm/core_cia.h> 29 30#include "proto.h" 31#include "irq_impl.h" 32#include "pci_impl.h" 33#include "machvec_impl.h" 34 35 36/* Note mask bit is true for ENABLED irqs. */ 37static int cached_irq_mask; 38 39static inline void 40mikasa_update_irq_hw(int mask) 41{ 42 outw(mask, 0x536); 43} 44 45static inline void 46mikasa_enable_irq(unsigned int irq) 47{ 48 mikasa_update_irq_hw(cached_irq_mask |= 1 << (irq - 16)); 49} 50 51static void 52mikasa_disable_irq(unsigned int irq) 53{ 54 mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (irq - 16))); 55} 56 57static unsigned int 58mikasa_startup_irq(unsigned int irq) 59{ 60 mikasa_enable_irq(irq); 61 return 0; 62} 63 64static void 65mikasa_end_irq(unsigned int irq) 66{ 67 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 68 mikasa_enable_irq(irq); 69} 70 71static struct hw_interrupt_type mikasa_irq_type = { 72 typename: "MIKASA", 73 startup: mikasa_startup_irq, 74 shutdown: mikasa_disable_irq, 75 enable: mikasa_enable_irq, 76 disable: mikasa_disable_irq, 77 ack: mikasa_disable_irq, 78 end: mikasa_end_irq, 79}; 80 81static void 82mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs) 83{ 84 unsigned long pld; 85 unsigned int i; 86 87 /* Read the interrupt summary registers */ 88 pld = (((~inw(0x534) & 0x0000ffffUL) << 16) 89 | (((unsigned long) inb(0xa0)) << 8) 90 | inb(0x20)); 91 92 /* 93 * Now for every possible bit set, work through them and call 94 * the appropriate interrupt handler. 95 */ 96 while (pld) { 97 i = ffz(~pld); 98 pld &= pld - 1; /* clear least bit set */ 99 if (i < 16) { 100 isa_device_interrupt(vector, regs); 101 } else { 102 handle_irq(i, regs); 103 } 104 } 105} 106 107static void __init 108mikasa_init_irq(void) 109{ 110 long i; 111 112 if (alpha_using_srm) 113 alpha_mv.device_interrupt = srm_device_interrupt; 114 115 mikasa_update_irq_hw(0); 116 117 for (i = 16; i < 32; ++i) { 118 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL; 119 irq_desc[i].handler = &mikasa_irq_type; 120 } 121 122 init_i8259a_irqs(); 123 common_init_isa_dma(); 124} 125 126 127/* 128 * PCI Fixup configuration. 129 * 130 * Summary @ 0x536: 131 * Bit Meaning 132 * 0 Interrupt Line A from slot 0 133 * 1 Interrupt Line B from slot 0 134 * 2 Interrupt Line C from slot 0 135 * 3 Interrupt Line D from slot 0 136 * 4 Interrupt Line A from slot 1 137 * 5 Interrupt line B from slot 1 138 * 6 Interrupt Line C from slot 1 139 * 7 Interrupt Line D from slot 1 140 * 8 Interrupt Line A from slot 2 141 * 9 Interrupt Line B from slot 2 142 *10 Interrupt Line C from slot 2 143 *11 Interrupt Line D from slot 2 144 *12 NCR 810 SCSI 145 *13 Power Supply Fail 146 *14 Temperature Warn 147 *15 Reserved 148 * 149 * The device to slot mapping looks like: 150 * 151 * Slot Device 152 * 6 NCR SCSI controller 153 * 7 Intel PCI-EISA bridge chip 154 * 11 PCI on board slot 0 155 * 12 PCI on board slot 1 156 * 13 PCI on board slot 2 157 * 158 * 159 * This two layered interrupt approach means that we allocate IRQ 16 and 160 * above for PCI interrupts. The IRQ relates to which bit the interrupt 161 * comes in on. This makes interrupt processing much easier. 162 */ 163 164static int __init 165mikasa_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 166{ 167 static char irq_tab[8][5] __initdata = { 168 /*INT INTA INTB INTC INTD */ 169 {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */ 170 { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ 171 { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */ 172 { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */ 173 { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */ 174 { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */ 175 { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */ 176 { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */ 177 }; 178 const long min_idsel = 6, max_idsel = 13, irqs_per_slot = 5; 179 return COMMON_TABLE_LOOKUP; 180} 181 182 183#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) 184static void 185mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr, 186 struct pt_regs * regs) 187{ 188#define MCHK_NO_DEVSEL 0x205U 189#define MCHK_NO_TABT 0x204U 190 191 struct el_common *mchk_header; 192 unsigned int code; 193 194 mchk_header = (struct el_common *)la_ptr; 195 196 /* Clear the error before any reporting. */ 197 mb(); 198 mb(); /* magic */ 199 draina(); 200 apecs_pci_clr_err(); 201 wrmces(0x7); 202 mb(); 203 204 code = mchk_header->code; 205 process_mcheck_info(vector, la_ptr, regs, "MIKASA APECS", 206 (mcheck_expected(0) 207 && (code == MCHK_NO_DEVSEL 208 || code == MCHK_NO_TABT))); 209} 210#endif 211 212 213/* 214 * The System Vector 215 */ 216 217#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) 218struct alpha_machine_vector mikasa_mv __initmv = { 219 vector_name: "Mikasa", 220 DO_EV4_MMU, 221 DO_DEFAULT_RTC, 222 DO_APECS_IO, 223 DO_APECS_BUS, 224 machine_check: mikasa_apecs_machine_check, 225 max_dma_address: ALPHA_MAX_DMA_ADDRESS, 226 min_io_address: DEFAULT_IO_BASE, 227 min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE, 228 229 nr_irqs: 32, 230 device_interrupt: mikasa_device_interrupt, 231 232 init_arch: apecs_init_arch, 233 init_irq: mikasa_init_irq, 234 init_rtc: common_init_rtc, 235 init_pci: common_init_pci, 236 kill_arch: NULL, 237 pci_map_irq: mikasa_map_irq, 238 pci_swizzle: common_swizzle, 239}; 240ALIAS_MV(mikasa) 241#endif 242 243#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO) 244struct alpha_machine_vector mikasa_primo_mv __initmv = { 245 vector_name: "Mikasa-Primo", 246 DO_EV5_MMU, 247 DO_DEFAULT_RTC, 248 DO_CIA_IO, 249 DO_CIA_BUS, 250 machine_check: cia_machine_check, 251 max_dma_address: ALPHA_MAX_DMA_ADDRESS, 252 min_io_address: DEFAULT_IO_BASE, 253 min_mem_address: CIA_DEFAULT_MEM_BASE, 254 255 nr_irqs: 32, 256 device_interrupt: mikasa_device_interrupt, 257 258 init_arch: cia_init_arch, 259 init_irq: mikasa_init_irq, 260 init_rtc: common_init_rtc, 261 init_pci: cia_init_pci, 262 pci_map_irq: mikasa_map_irq, 263 pci_swizzle: common_swizzle, 264}; 265ALIAS_MV(mikasa_primo) 266#endif 267