fixup-sni.c
4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* SNI specific PCI support for RM200/RM300.
*
* Copyright (C) 1997 - 2000, 2003, 04 Ralf Baechle (ralf@linux-mips.org)
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/mipsregs.h>
#include <asm/sni.h>
#include <irq.h>
/*
* PCIMT Shortcuts ...
*/
#define SCSI PCIMT_IRQ_SCSI
#define ETH PCIMT_IRQ_ETHERNET
#define INTA PCIMT_IRQ_INTA
#define INTB PCIMT_IRQ_INTB
#define INTC PCIMT_IRQ_INTC
#define INTD PCIMT_IRQ_INTD
/*
* Device 0: PCI EISA Bridge (directly routed)
* Device 1: NCR53c810 SCSI (directly routed)
* Device 2: PCnet32 Ethernet (directly routed)
* Device 3: VGA (routed to INTB)
* Device 4: Unused
* Device 5: Slot 2
* Device 6: Slot 3
* Device 7: Slot 4
*
* Documentation says the VGA is device 5 and device 3 is unused but that
* seem to be a documentation error. At least on my RM200C the Cirrus
* Logic CL-GD5434 VGA is device 3.
*/
static char irq_tab_rm200[8][5] __initdata = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* EISA bridge */
{ SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
{ ETH, ETH, ETH, ETH, ETH }, /* Ethernet */
{ INTB, INTB, INTB, INTB, INTB }, /* VGA */
{ 0, 0, 0, 0, 0 }, /* Unused */
{ 0, INTB, INTC, INTD, INTA }, /* Slot 2 */
{ 0, INTC, INTD, INTA, INTB }, /* Slot 3 */
{ 0, INTD, INTA, INTB, INTC }, /* Slot 4 */
};
/*
* In Revision D of the RM300 Device 2 has become a normal purpose Slot 1
*
* The VGA card is optional for RM300 systems.
*/
static char irq_tab_rm300d[8][5] __initdata = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* EISA bridge */
{ SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
{ 0, INTC, INTD, INTA, INTB }, /* Slot 1 */
{ INTB, INTB, INTB, INTB, INTB }, /* VGA */
{ 0, 0, 0, 0, 0 }, /* Unused */
{ 0, INTB, INTC, INTD, INTA }, /* Slot 2 */
{ 0, INTC, INTD, INTA, INTB }, /* Slot 3 */
{ 0, INTD, INTA, INTB, INTC }, /* Slot 4 */
};
static char irq_tab_rm300e[5][5] __initdata = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* HOST bridge */
{ SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */
{ 0, INTC, INTD, INTA, INTB }, /* Bridge/i960 */
{ 0, INTD, INTA, INTB, INTC }, /* Slot 1 */
{ 0, INTA, INTB, INTC, INTD }, /* Slot 2 */
};
#undef SCSI
#undef ETH
#undef INTA
#undef INTB
#undef INTC
#undef INTD
/*
* PCIT Shortcuts ...
*/
#define SCSI0 PCIT_IRQ_SCSI0
#define SCSI1 PCIT_IRQ_SCSI1
#define ETH PCIT_IRQ_ETHERNET
#define INTA PCIT_IRQ_INTA
#define INTB PCIT_IRQ_INTB
#define INTC PCIT_IRQ_INTC
#define INTD PCIT_IRQ_INTD
static char irq_tab_pcit[13][5] __initdata = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* HOST bridge */
{ SCSI0, SCSI0, SCSI0, SCSI0, SCSI0 }, /* SCSI */
{ SCSI1, SCSI1, SCSI1, SCSI1, SCSI1 }, /* SCSI */
{ ETH, ETH, ETH, ETH, ETH }, /* Ethernet */
{ 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */
{ 0, 0, 0, 0, 0 }, /* Unused */
{ 0, 0, 0, 0, 0 }, /* Unused */
{ 0, 0, 0, 0, 0 }, /* Unused */
{ 0, INTA, INTB, INTC, INTD }, /* Slot 1 */
{ 0, INTB, INTC, INTD, INTA }, /* Slot 2 */
{ 0, INTC, INTD, INTA, INTB }, /* Slot 3 */
{ 0, INTD, INTA, INTB, INTC }, /* Slot 4 */
{ 0, INTA, INTB, INTC, INTD }, /* Slot 5 */
};
static char irq_tab_pcit_cplus[13][5] __initdata = {
/* INTA INTB INTC INTD */
{ 0, 0, 0, 0, 0 }, /* HOST bridge */
{ 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */
{ 0, 0, 0, 0, 0 }, /* PCI-EISA */
{ 0, 0, 0, 0, 0 }, /* Unused */
{ 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */
{ 0, INTB, INTC, INTD, INTA }, /* fixup */
};
static inline int is_rm300_revd(void)
{
unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR;
return (csmsr & 0xa0) == 0x20;
}
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (sni_brd_type) {
case SNI_BRD_PCI_TOWER_CPLUS:
if (slot == 4) {
/*
* SNI messed up interrupt wiring for onboard
* PCI bus 1; we need to fix this up here
*/
while (dev && dev->bus->number != 1)
dev = dev->bus->self;
if (dev && dev->devfn >= PCI_DEVFN(4, 0))
slot = 5;
}
return irq_tab_pcit_cplus[slot][pin];
case SNI_BRD_PCI_TOWER:
return irq_tab_pcit[slot][pin];
case SNI_BRD_PCI_MTOWER:
if (is_rm300_revd())
return irq_tab_rm300d[slot][pin];
/* fall through */
case SNI_BRD_PCI_DESKTOP:
return irq_tab_rm200[slot][pin];
case SNI_BRD_PCI_MTOWER_CPLUS:
return irq_tab_rm300e[slot][pin];
}
return 0;
}
/* Do platform specific device initialization at pci_enable_device() time */
int pcibios_plat_dev_init(struct pci_dev *dev)
{
return 0;
}