File: /usr/src/linux/arch/alpha/kernel/sys_sable.c

1     /*
2      *	linux/arch/alpha/kernel/sys_sable.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 Sable and Sable-Gamma systems.
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/mmu_context.h>
24     #include <asm/io.h>
25     #include <asm/pgtable.h>
26     #include <asm/core_t2.h>
27     
28     #include "proto.h"
29     #include "irq_impl.h"
30     #include "pci_impl.h"
31     #include "machvec_impl.h"
32     
33     spinlock_t sable_irq_lock = SPIN_LOCK_UNLOCKED;
34     
35     /*
36      *   For SABLE, which is really baroque, we manage 40 IRQ's, but the
37      *   hardware really only supports 24, not via normal ISA PIC,
38      *   but cascaded custom 8259's, etc.
39      *	 0-7  (char at 536)
40      *	 8-15 (char at 53a)
41      *	16-23 (char at 53c)
42      *
43      * Summary Registers (536/53a/53c):
44      *
45      * Bit      Meaning               Kernel IRQ
46      *------------------------------------------
47      * 0        PCI slot 0			34
48      * 1        NCR810 (builtin)		33
49      * 2        TULIP (builtin)		32
50      * 3        mouse			12
51      * 4        PCI slot 1			35
52      * 5        PCI slot 2			36
53      * 6        keyboard			1
54      * 7        floppy			6
55      * 8        COM2			3
56      * 9        parallel port		7
57      *10        EISA irq 3			-
58      *11        EISA irq 4			-
59      *12        EISA irq 5			5
60      *13        EISA irq 6			-
61      *14        EISA irq 7			-
62      *15        COM1			4
63      *16        EISA irq 9			9
64      *17        EISA irq 10			10
65      *18        EISA irq 11			11
66      *19        EISA irq 12			-
67      *20        EISA irq 13			-
68      *21        EISA irq 14			14
69      *22        NC				15
70      *23        IIC				-
71      */
72     
73     static struct 
74     {
75     	char irq_to_mask[40];
76     	char mask_to_irq[40];
77     
78     	/* Note mask bit is true for DISABLED irqs.  */
79     	unsigned long shadow_mask;
80     } sable_irq_swizzle = {
81     	{
82     		-1,  6, -1,  8, 15, 12,  7,  9,	/* pseudo PIC  0-7  */
83     		-1, 16, 17, 18,  3, -1, 21, 22,	/* pseudo PIC  8-15 */
84     		-1, -1, -1, -1, -1, -1, -1, -1,	/* pseudo EISA 0-7  */
85     		-1, -1, -1, -1, -1, -1, -1, -1,	/* pseudo EISA 8-15 */
86     		 2,  1,  0,  4,  5, -1, -1, -1,	/* pseudo PCI */
87     	},
88     	{
89     		34, 33, 32, 12, 35, 36,  1,  6,	/* mask 0-7  */
90     		 3,  7, -1, -1,  5, -1, -1,  4,	/* mask 8-15  */
91     		 9, 10, 11, -1, -1, 14, 15, -1,	/* mask 16-23  */
92     	},
93     	-1
94     };
95     
96     static inline void
97     sable_update_irq_hw(unsigned long bit, unsigned long mask)
98     {
99     	int port = 0x537;
100     
101     	if (bit >= 16) {
102     		port = 0x53d;
103     		mask >>= 16;
104     	} else if (bit >= 8) {
105     		port = 0x53b;
106     		mask >>= 8;
107     	}
108     
109     	outb(mask, port);
110     }
111     
112     static inline void
113     sable_ack_irq_hw(unsigned long bit)
114     {
115     	int port, val1, val2;
116     
117     	if (bit >= 16) {
118     		port = 0x53c;
119     		val1 = 0xE0 | (bit - 16);
120     		val2 = 0xE0 | 4;
121     	} else if (bit >= 8) {
122     		port = 0x53a;
123     		val1 = 0xE0 | (bit - 8);
124     		val2 = 0xE0 | 3;
125     	} else {
126     		port = 0x536;
127     		val1 = 0xE0 | (bit - 0);
128     		val2 = 0xE0 | 1;
129     	}
130     
131     	outb(val1, port);	/* ack the slave */
132     	outb(val2, 0x534);	/* ack the master */
133     }
134     
135     static inline void
136     sable_enable_irq(unsigned int irq)
137     {
138     	unsigned long bit, mask;
139     
140     	bit = sable_irq_swizzle.irq_to_mask[irq];
141     	spin_lock(&sable_irq_lock);
142     	mask = sable_irq_swizzle.shadow_mask &= ~(1UL << bit);
143     	sable_update_irq_hw(bit, mask);
144     	spin_unlock(&sable_irq_lock);
145     }
146     
147     static void
148     sable_disable_irq(unsigned int irq)
149     {
150     	unsigned long bit, mask;
151     
152     	bit = sable_irq_swizzle.irq_to_mask[irq];
153     	spin_lock(&sable_irq_lock);
154     	mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
155     	sable_update_irq_hw(bit, mask);
156     	spin_unlock(&sable_irq_lock);
157     }
158     
159     static unsigned int
160     sable_startup_irq(unsigned int irq)
161     {
162     	sable_enable_irq(irq);
163     	return 0;
164     }
165     
166     static void
167     sable_end_irq(unsigned int irq)
168     {
169     	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
170     		sable_enable_irq(irq);
171     }
172     
173     static void
174     sable_mask_and_ack_irq(unsigned int irq)
175     {
176     	unsigned long bit, mask;
177     
178     	bit = sable_irq_swizzle.irq_to_mask[irq];
179     	spin_lock(&sable_irq_lock);
180     	mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
181     	sable_update_irq_hw(bit, mask);
182     	sable_ack_irq_hw(bit);
183     	spin_unlock(&sable_irq_lock);
184     }
185     
186     static struct hw_interrupt_type sable_irq_type = {
187     	typename:	"SABLE",
188     	startup:	sable_startup_irq,
189     	shutdown:	sable_disable_irq,
190     	enable:		sable_enable_irq,
191     	disable:	sable_disable_irq,
192     	ack:		sable_mask_and_ack_irq,
193     	end:		sable_end_irq,
194     };
195     
196     static void 
197     sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
198     {
199     	/* Note that the vector reported by the SRM PALcode corresponds
200     	   to the interrupt mask bits, but we have to manage via more
201     	   normal IRQs.  */
202     
203     	int bit, irq;
204     
205     	bit = (vector - 0x800) >> 4;
206     	irq = sable_irq_swizzle.mask_to_irq[bit];
207     	handle_irq(irq, regs);
208     }
209     
210     static void __init
211     sable_init_irq(void)
212     {
213     	long i;
214     
215     	outb(-1, 0x537);	/* slave 0 */
216     	outb(-1, 0x53b);	/* slave 1 */
217     	outb(-1, 0x53d);	/* slave 2 */
218     	outb(0x44, 0x535);	/* enable cascades in master */
219     
220     	for (i = 0; i < 40; ++i) {
221     		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
222     		irq_desc[i].handler = &sable_irq_type;
223     	}
224     	
225     	common_init_isa_dma();
226     }
227     
228     
229     /*
230      * PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
231      *
232      * The device to slot mapping looks like:
233      *
234      * Slot     Device
235      *  0       TULIP
236      *  1       SCSI
237      *  2       PCI-EISA bridge
238      *  3       none
239      *  4       none
240      *  5       none
241      *  6       PCI on board slot 0
242      *  7       PCI on board slot 1
243      *  8       PCI on board slot 2
244      *   
245      *
246      * This two layered interrupt approach means that we allocate IRQ 16 and 
247      * above for PCI interrupts.  The IRQ relates to which bit the interrupt
248      * comes in on.  This makes interrupt processing much easier.
249      */
250     /*
251      * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
252      * with the values in the irq swizzling tables above.
253      */
254     
255     static int __init
256     sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
257     {
258             static char irq_tab[9][5] __initdata = {
259     		/*INT    INTA   INTB   INTC   INTD */
260     		{ 32+0,  32+0,  32+0,  32+0,  32+0},  /* IdSel 0,  TULIP  */
261     		{ 32+1,  32+1,  32+1,  32+1,  32+1},  /* IdSel 1,  SCSI   */
262     		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 2,  SIO   */
263     		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 3,  none   */
264     		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 4,  none   */
265     		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 5,  none   */
266     		{ 32+2,  32+2,  32+2,  32+2,  32+2},  /* IdSel 6,  slot 0 */
267     		{ 32+3,  32+3,  32+3,  32+3,  32+3},  /* IdSel 7,  slot 1 */
268     		{ 32+4,  32+4,  32+4,  32+4,  32+4},  /* IdSel 8,  slot 2 */
269             };
270     	const long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
271     	return COMMON_TABLE_LOOKUP;
272     }
273     
274     
275     /*
276      * The System Vectors
277      *
278      * In order that T2_HAE_ADDRESS should be a constant, we play
279      * these games with GAMMA_BIAS.
280      */
281     
282     #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_GAMMA)
283     #undef GAMMA_BIAS
284     #define GAMMA_BIAS 0
285     struct alpha_machine_vector sable_mv __initmv = {
286     	vector_name:		"Sable",
287     	DO_EV4_MMU,
288     	DO_DEFAULT_RTC,
289     	DO_T2_IO,
290     	DO_T2_BUS,
291     	machine_check:		t2_machine_check,
292     	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
293     	min_io_address:		EISA_DEFAULT_IO_BASE,
294     	min_mem_address:	DEFAULT_MEM_BASE,
295     
296     	nr_irqs:		40,
297     	device_interrupt:	sable_srm_device_interrupt,
298     
299     	init_arch:		t2_init_arch,
300     	init_irq:		sable_init_irq,
301     	init_rtc:		common_init_rtc,
302     	init_pci:		common_init_pci,
303     	kill_arch:		NULL,
304     	pci_map_irq:		sable_map_irq,
305     	pci_swizzle:		common_swizzle,
306     
307     	sys: { t2: {
308     	    gamma_bias:		0
309     	} }
310     };
311     ALIAS_MV(sable)
312     #endif
313     
314     #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_GAMMA)
315     #undef GAMMA_BIAS
316     #define GAMMA_BIAS _GAMMA_BIAS
317     struct alpha_machine_vector sable_gamma_mv __initmv = {
318     	vector_name:		"Sable-Gamma",
319     	DO_EV5_MMU,
320     	DO_DEFAULT_RTC,
321     	DO_T2_IO,
322     	DO_T2_BUS,
323     	machine_check:		t2_machine_check,
324     	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
325     	min_io_address:		EISA_DEFAULT_IO_BASE,
326     	min_mem_address:	DEFAULT_MEM_BASE,
327     
328     	nr_irqs:		40,
329     	device_interrupt:	sable_srm_device_interrupt,
330     
331     	init_arch:		t2_init_arch,
332     	init_irq:		sable_init_irq,
333     	init_rtc:		common_init_rtc,
334     	init_pci:		common_init_pci,
335     	pci_map_irq:		sable_map_irq,
336     	pci_swizzle:		common_swizzle,
337     
338     	sys: { t2: {
339     	    gamma_bias:		_GAMMA_BIAS
340     	} }
341     };
342     ALIAS_MV(sable_gamma)
343     #endif
344