OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sparc64/] [kernel/] [isa.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
#include <linux/kernel.h>
2
#include <linux/init.h>
3
#include <linux/pci.h>
4
#include <linux/slab.h>
5
#include <asm/oplib.h>
6
#include <asm/isa.h>
7
 
8
struct isa_bridge *isa_chain;
9
 
10
static void __init fatal_err(const char *reason)
11
{
12
        prom_printf("ISA: fatal error, %s.\n", reason);
13
}
14
 
15
static void __init report_dev(struct isa_device *isa_dev, int child)
16
{
17
        if (child)
18
                printk(" (%s)", isa_dev->prom_name);
19
        else
20
                printk(" [%s", isa_dev->prom_name);
21
}
22
 
23
static void __init isa_dev_get_resource(struct isa_device *isa_dev,
24
                                        struct linux_prom_registers *pregs,
25
                                        int pregs_size)
26
{
27
        unsigned long base, len;
28
        int prop_len;
29
 
30
        prop_len = prom_getproperty(isa_dev->prom_node, "reg",
31
                                    (char *) pregs, pregs_size);
32
 
33
        if (prop_len <= 0)
34
                return;
35
 
36
        /* Only the first one is interesting. */
37
        len = pregs[0].reg_size;
38
        base = (((unsigned long)pregs[0].which_io << 32) |
39
                (unsigned long)pregs[0].phys_addr);
40
        base += isa_dev->bus->parent->io_space.start;
41
 
42
        isa_dev->resource.start = base;
43
        isa_dev->resource.end   = (base + len - 1UL);
44
        isa_dev->resource.flags = IORESOURCE_IO;
45
        isa_dev->resource.name  = isa_dev->prom_name;
46
 
47
        request_resource(&isa_dev->bus->parent->io_space,
48
                         &isa_dev->resource);
49
}
50
 
51
/* I can't believe they didn't put a real INO in the isa device
52
 * interrupts property.  The whole point of the OBP properties
53
 * is to shield the kernel from IRQ routing details.
54
 *
55
 * The P1275 standard for ISA devices seems to also have been
56
 * totally ignored.
57
 *
58
 * On later systems, an interrupt-map and interrupt-map-mask scheme
59
 * akin to EBUS is used.
60
 */
61
static struct {
62
        int     obp_irq;
63
        int     pci_ino;
64
} grover_irq_table[] = {
65
        { 1, 0x00 },    /* dma, unknown ino at this point */
66
        { 2, 0x27 },    /* floppy */
67
        { 3, 0x22 },    /* parallel */
68
        { 4, 0x2b },    /* serial */
69
        { 5, 0x25 },    /* acpi power management */
70
 
71
        { 0, 0x00 }      /* end of table */
72
};
73
 
74
static int __init isa_dev_get_irq_using_imap(struct isa_device *isa_dev,
75
                                             struct isa_bridge *isa_br,
76
                                             int *interrupt,
77
                                             struct linux_prom_registers *pregs)
78
{
79
        unsigned int hi, lo, irq;
80
        int i;
81
 
82
        hi = pregs->which_io & isa_br->isa_intmask.phys_hi;
83
        lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo;
84
        irq = *interrupt & isa_br->isa_intmask.interrupt;
85
        for (i = 0; i < isa_br->num_isa_intmap; i++) {
86
                if ((isa_br->isa_intmap[i].phys_hi == hi) &&
87
                    (isa_br->isa_intmap[i].phys_lo == lo) &&
88
                    (isa_br->isa_intmap[i].interrupt == irq)) {
89
                        *interrupt = isa_br->isa_intmap[i].cinterrupt;
90
                        return 0;
91
                }
92
        }
93
        return -1;
94
}
95
 
96
static void __init isa_dev_get_irq(struct isa_device *isa_dev,
97
                                   struct linux_prom_registers *pregs)
98
{
99
        int irq_prop;
100
 
101
        irq_prop = prom_getintdefault(isa_dev->prom_node,
102
                                      "interrupts", -1);
103
        if (irq_prop <= 0) {
104
                goto no_irq;
105
        } else {
106
                struct pci_controller_info *pcic;
107
                struct pci_pbm_info *pbm;
108
                int i;
109
 
110
                if (isa_dev->bus->num_isa_intmap) {
111
                        if (!isa_dev_get_irq_using_imap(isa_dev,
112
                                                        isa_dev->bus,
113
                                                        &irq_prop,
114
                                                        pregs))
115
                                goto route_irq;
116
                }
117
 
118
                for (i = 0; grover_irq_table[i].obp_irq != 0; i++) {
119
                        if (grover_irq_table[i].obp_irq == irq_prop) {
120
                                int ino = grover_irq_table[i].pci_ino;
121
 
122
                                if (ino == 0)
123
                                        goto no_irq;
124
 
125
                                irq_prop = ino;
126
                                goto route_irq;
127
                        }
128
                }
129
                goto no_irq;
130
 
131
route_irq:
132
                pbm = isa_dev->bus->parent;
133
                pcic = pbm->parent;
134
                isa_dev->irq = pcic->irq_build(pbm, NULL, irq_prop);
135
                return;
136
        }
137
 
138
no_irq:
139
        isa_dev->irq = PCI_IRQ_NONE;
140
}
141
 
142
static void __init isa_fill_children(struct isa_device *parent_isa_dev)
143
{
144
        int node = prom_getchild(parent_isa_dev->prom_node);
145
 
146
        if (node == 0)
147
                return;
148
 
149
        printk(" ->");
150
        while (node != 0) {
151
                struct linux_prom_registers regs[PROMREG_MAX];
152
                struct isa_device *isa_dev;
153
                int prop_len;
154
 
155
                isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
156
                if (!isa_dev) {
157
                        fatal_err("cannot allocate child isa_dev");
158
                        prom_halt();
159
                }
160
 
161
                memset(isa_dev, 0, sizeof(*isa_dev));
162
 
163
                /* Link it in to parent. */
164
                isa_dev->next = parent_isa_dev->child;
165
                parent_isa_dev->child = isa_dev;
166
 
167
                isa_dev->bus = parent_isa_dev->bus;
168
                isa_dev->prom_node = node;
169
                prop_len = prom_getproperty(node, "name",
170
                                            (char *) isa_dev->prom_name,
171
                                            sizeof(isa_dev->prom_name));
172
                if (prop_len <= 0) {
173
                        fatal_err("cannot get child isa_dev OBP node name");
174
                        prom_halt();
175
                }
176
 
177
                prop_len = prom_getproperty(node, "compatible",
178
                                            (char *) isa_dev->compatible,
179
                                            sizeof(isa_dev->compatible));
180
 
181
                /* Not having this is OK. */
182
                if (prop_len <= 0)
183
                        isa_dev->compatible[0] = '\0';
184
 
185
                isa_dev_get_resource(isa_dev, regs, sizeof(regs));
186
                isa_dev_get_irq(isa_dev, regs);
187
 
188
                report_dev(isa_dev, 1);
189
 
190
                node = prom_getsibling(node);
191
        }
192
}
193
 
194
static void __init isa_fill_devices(struct isa_bridge *isa_br)
195
{
196
        int node = prom_getchild(isa_br->prom_node);
197
 
198
        while (node != 0) {
199
                struct linux_prom_registers regs[PROMREG_MAX];
200
                struct isa_device *isa_dev;
201
                int prop_len;
202
 
203
                isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
204
                if (!isa_dev) {
205
                        fatal_err("cannot allocate isa_dev");
206
                        prom_halt();
207
                }
208
 
209
                memset(isa_dev, 0, sizeof(*isa_dev));
210
 
211
                /* Link it in. */
212
                isa_dev->next = NULL;
213
                if (isa_br->devices == NULL) {
214
                        isa_br->devices = isa_dev;
215
                } else {
216
                        struct isa_device *tmp = isa_br->devices;
217
 
218
                        while (tmp->next)
219
                                tmp = tmp->next;
220
 
221
                        tmp->next = isa_dev;
222
                }
223
 
224
                isa_dev->bus = isa_br;
225
                isa_dev->prom_node = node;
226
                prop_len = prom_getproperty(node, "name",
227
                                            (char *) isa_dev->prom_name,
228
                                            sizeof(isa_dev->prom_name));
229
                if (prop_len <= 0) {
230
                        fatal_err("cannot get isa_dev OBP node name");
231
                        prom_halt();
232
                }
233
 
234
                prop_len = prom_getproperty(node, "compatible",
235
                                            (char *) isa_dev->compatible,
236
                                            sizeof(isa_dev->compatible));
237
 
238
                /* Not having this is OK. */
239
                if (prop_len <= 0)
240
                        isa_dev->compatible[0] = '\0';
241
 
242
                isa_dev_get_resource(isa_dev, regs, sizeof(regs));
243
                isa_dev_get_irq(isa_dev, regs);
244
 
245
                report_dev(isa_dev, 0);
246
 
247
                isa_fill_children(isa_dev);
248
 
249
                printk("]");
250
 
251
                node = prom_getsibling(node);
252
        }
253
}
254
 
255
void __init isa_init(void)
256
{
257
        struct pci_dev *pdev;
258
        unsigned short vendor, device;
259
        int index = 0;
260
 
261
        vendor = PCI_VENDOR_ID_AL;
262
        device = PCI_DEVICE_ID_AL_M1533;
263
 
264
        pdev = NULL;
265
        while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) {
266
                struct pcidev_cookie *pdev_cookie;
267
                struct pci_pbm_info *pbm;
268
                struct isa_bridge *isa_br;
269
                int prop_len;
270
 
271
                pdev_cookie = pdev->sysdata;
272
                if (!pdev_cookie) {
273
                        printk("ISA: Warning, ISA bridge ignored due to "
274
                               "lack of OBP data.\n");
275
                        continue;
276
                }
277
                pbm = pdev_cookie->pbm;
278
 
279
                isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
280
                if (!isa_br) {
281
                        fatal_err("cannot allocate isa_bridge");
282
                        prom_halt();
283
                }
284
 
285
                memset(isa_br, 0, sizeof(*isa_br));
286
 
287
                /* Link it in. */
288
                isa_br->next = isa_chain;
289
                isa_chain = isa_br;
290
 
291
                isa_br->parent = pbm;
292
                isa_br->self = pdev;
293
                isa_br->index = index++;
294
                isa_br->prom_node = pdev_cookie->prom_node;
295
                strncpy(isa_br->prom_name, pdev_cookie->prom_name,
296
                        sizeof(isa_br->prom_name));
297
 
298
                prop_len = prom_getproperty(isa_br->prom_node,
299
                                            "ranges",
300
                                            (char *) isa_br->isa_ranges,
301
                                            sizeof(isa_br->isa_ranges));
302
                if (prop_len <= 0)
303
                        isa_br->num_isa_ranges = 0;
304
                else
305
                        isa_br->num_isa_ranges =
306
                                (prop_len / sizeof(struct linux_prom_isa_ranges));
307
 
308
                prop_len = prom_getproperty(isa_br->prom_node,
309
                                            "interrupt-map",
310
                                            (char *) isa_br->isa_intmap,
311
                                            sizeof(isa_br->isa_intmap));
312
                if (prop_len <= 0)
313
                        isa_br->num_isa_intmap = 0;
314
                else
315
                        isa_br->num_isa_intmap =
316
                                (prop_len / sizeof(struct linux_prom_isa_intmap));
317
 
318
                prop_len = prom_getproperty(isa_br->prom_node,
319
                                            "interrupt-map-mask",
320
                                            (char *) &(isa_br->isa_intmask),
321
                                            sizeof(isa_br->isa_intmask));
322
 
323
                printk("isa%d:", isa_br->index);
324
 
325
                isa_fill_devices(isa_br);
326
 
327
                printk("\n");
328
        }
329
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.