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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: pci.c,v 1.1.1.1 2004-04-15 01:34:11 phoenix Exp $
2
 * pci.c: UltraSparc PCI controller support.
3
 *
4
 * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
5
 * Copyright (C) 1998, 1999 Eddie C. Dost   (ecd@skynet.be)
6
 * Copyright (C) 1999 Jakub Jelinek   (jj@ultra.linux.cz)
7
 */
8
 
9
#include <linux/config.h>
10
#include <linux/kernel.h>
11
#include <linux/string.h>
12
#include <linux/sched.h>
13
#include <linux/capability.h>
14
#include <linux/errno.h>
15
#include <linux/smp_lock.h>
16
#include <linux/init.h>
17
 
18
#include <asm/uaccess.h>
19
#include <asm/pbm.h>
20
#include <asm/irq.h>
21
#include <asm/ebus.h>
22
#include <asm/isa.h>
23
 
24
unsigned long pci_memspace_mask = 0xffffffffUL;
25
 
26
#ifndef CONFIG_PCI
27
/* A "nop" PCI implementation. */
28
asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
29
                                  unsigned long off, unsigned long len,
30
                                  unsigned char *buf)
31
{
32
        return 0;
33
}
34
asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
35
                                   unsigned long off, unsigned long len,
36
                                   unsigned char *buf)
37
{
38
        return 0;
39
}
40
#else
41
 
42
/* List of all PCI controllers found in the system. */
43
spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
44
struct pci_controller_info *pci_controller_root = NULL;
45
 
46
/* Each PCI controller found gets a unique index. */
47
int pci_num_controllers = 0;
48
 
49
/* Given an 8-bit PCI bus number, this yields the
50
 * controlling PBM module info.
51
 *
52
 * Some explanation is in order here.  The Linux APIs for
53
 * the PCI subsystem require that the configuration space
54
 * types are enough to signify PCI configuration space
55
 * accesses correctly.  This gives us 8-bits for the bus
56
 * number, however we have multiple PCI controllers on
57
 * UltraSparc systems.
58
 *
59
 * So what we do is give the PCI busses under each controller
60
 * a unique portion of the 8-bit PCI bus number space.
61
 * Therefore one can obtain the controller from the bus
62
 * number.  For example, say PSYCHO PBM-A a subordinate bus
63
 * space of 0 to 4, and PBM-B has a space of 0 to 2.  PBM-A
64
 * will use 0 to 4, and PBM-B will use 5 to 7.
65
 */
66
struct pci_pbm_info *pci_bus2pbm[256];
67
unsigned char pci_highest_busnum = 0;
68
 
69
/* At boot time the user can give the kernel a command
70
 * line option which controls if and how PCI devices
71
 * are reordered at PCI bus probing time.
72
 */
73
int pci_device_reorder = 0;
74
 
75
spinlock_t pci_poke_lock = SPIN_LOCK_UNLOCKED;
76
volatile int pci_poke_in_progress;
77
volatile int pci_poke_cpu = -1;
78
volatile int pci_poke_faulted;
79
 
80
/* Probe for all PCI controllers in the system. */
81
extern void sabre_init(int, char *);
82
extern void psycho_init(int, char *);
83
extern void schizo_init(int, char *);
84
extern void schizo_plus_init(int, char *);
85
extern void tomatillo_init(int, char *);
86
 
87
static struct {
88
        char *model_name;
89
        void (*init)(int, char *);
90
} pci_controller_table[] = {
91
        { "SUNW,sabre", sabre_init },
92
        { "pci108e,a000", sabre_init },
93
        { "pci108e,a001", sabre_init },
94
        { "SUNW,psycho", psycho_init },
95
        { "pci108e,8000", psycho_init },
96
        { "SUNW,schizo", schizo_init },
97
        { "pci108e,8001", schizo_init },
98
        { "SUNW,schizo+", schizo_plus_init },
99
        { "pci108e,8002", schizo_plus_init },
100
        { "SUNW,tomatillo", tomatillo_init },
101
        { "pci108e,a801", tomatillo_init },
102
};
103
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
104
                                  sizeof(pci_controller_table[0]))
105
 
106
static int pci_controller_init(char *model_name, int namelen, int node)
107
{
108
        int i;
109
 
110
        for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) {
111
                if (!strncmp(model_name,
112
                             pci_controller_table[i].model_name,
113
                             namelen)) {
114
                        pci_controller_table[i].init(node, model_name);
115
                        return 1;
116
                }
117
        }
118
        printk("PCI: Warning unknown controller, model name [%s]\n",
119
               model_name);
120
        printk("PCI: Ignoring controller...\n");
121
 
122
        return 0;
123
}
124
 
125
static int pci_is_controller(char *model_name, int namelen, int node)
126
{
127
        int i;
128
 
129
        for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) {
130
                if (!strncmp(model_name,
131
                             pci_controller_table[i].model_name,
132
                             namelen)) {
133
                        return 1;
134
                }
135
        }
136
        return 0;
137
}
138
 
139
 
140
static int pci_controller_scan(int (*handler)(char *, int, int))
141
{
142
        char namebuf[64];
143
        int node;
144
        int count = 0;
145
 
146
        node = prom_getchild(prom_root_node);
147
        while ((node = prom_searchsiblings(node, "pci")) != 0) {
148
                int len;
149
 
150
                if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
151
                    (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
152
                        int item_len = 0;
153
 
154
                        /* Our value may be a multi-valued string in the
155
                         * case of some compatible properties. For sanity,
156
                         * only try the first one. */
157
 
158
                        while (namebuf[item_len] && len) {
159
                                len--;
160
                                item_len++;
161
                        }
162
 
163
                        if (handler(namebuf, item_len, node))
164
                                count++;
165
                }
166
 
167
                node = prom_getsibling(node);
168
                if (!node)
169
                        break;
170
        }
171
 
172
        return count;
173
}
174
 
175
 
176
/* Is there some PCI controller in the system?  */
177
int pcic_present(void)
178
{
179
        return pci_controller_scan(pci_is_controller);
180
}
181
 
182
/* Find each controller in the system, attach and initialize
183
 * software state structure for each and link into the
184
 * pci_controller_root.  Setup the controller enough such
185
 * that bus scanning can be done.
186
 */
187
static void pci_controller_probe(void)
188
{
189
        printk("PCI: Probing for controllers.\n");
190
 
191
        pci_controller_scan(pci_controller_init);
192
}
193
 
194
static void pci_scan_each_controller_bus(void)
195
{
196
        struct pci_controller_info *p;
197
        unsigned long flags;
198
 
199
        spin_lock_irqsave(&pci_controller_lock, flags);
200
        for (p = pci_controller_root; p; p = p->next)
201
                p->scan_bus(p);
202
        spin_unlock_irqrestore(&pci_controller_lock, flags);
203
}
204
 
205
/* Reorder the pci_dev chain, so that onboard devices come first
206
 * and then come the pluggable cards.
207
 */
208
static void __init pci_reorder_devs(void)
209
{
210
        struct list_head *pci_onboard = &pci_devices;
211
        struct list_head *walk = pci_onboard->next;
212
 
213
        while (walk != pci_onboard) {
214
                struct pci_dev *pdev = pci_dev_g(walk);
215
                struct list_head *walk_next = walk->next;
216
 
217
                if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
218
                        list_del(walk);
219
                        list_add(walk, pci_onboard);
220
                }
221
 
222
                walk = walk_next;
223
        }
224
}
225
 
226
extern void rs_init(void);
227
extern void clock_probe(void);
228
extern void power_init(void);
229
 
230
void __init pcibios_init(void)
231
{
232
        pci_controller_probe();
233
        if (pci_controller_root == NULL)
234
                return;
235
 
236
        pci_scan_each_controller_bus();
237
 
238
        if (pci_device_reorder)
239
                pci_reorder_devs();
240
 
241
        isa_init();
242
        ebus_init();
243
        rs_init();
244
        clock_probe();
245
        power_init();
246
}
247
 
248
struct pci_fixup pcibios_fixups[] = {
249
        { 0 }
250
};
251
 
252
void pcibios_fixup_bus(struct pci_bus *pbus)
253
{
254
        struct pci_pbm_info *pbm = pbus->sysdata;
255
 
256
        /* Generic PCI bus probing sets these to point at
257
         * &io{port,mem}_resouce which is wrong for us.
258
         */
259
        pbus->resource[0] = &pbm->io_space;
260
        pbus->resource[1] = &pbm->mem_space;
261
}
262
 
263
/* NOTE: This can get called before we've fixed up pdev->sysdata. */
264
int pci_claim_resource(struct pci_dev *pdev, int resource)
265
{
266
        struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number];
267
        struct resource *res = &pdev->resource[resource];
268
        struct resource *root;
269
 
270
        if (!pbm)
271
                return -EINVAL;
272
 
273
        if (res->flags & IORESOURCE_IO)
274
                root = &pbm->io_space;
275
        else
276
                root = &pbm->mem_space;
277
 
278
        pbm->parent->resource_adjust(pdev, res, root);
279
 
280
        return request_resource(root, res);
281
}
282
 
283
/*
284
 * Given the PCI bus a device resides on, try to
285
 * find an acceptable resource allocation for a
286
 * specific device resource..
287
 */
288
static int pci_assign_bus_resource(const struct pci_bus *bus,
289
        struct pci_dev *dev,
290
        struct resource *res,
291
        unsigned long size,
292
        unsigned long min,
293
        int resno)
294
{
295
        unsigned int type_mask;
296
        int i;
297
 
298
        type_mask = IORESOURCE_IO | IORESOURCE_MEM;
299
        for (i = 0 ; i < 4; i++) {
300
                struct resource *r = bus->resource[i];
301
                if (!r)
302
                        continue;
303
 
304
                /* type_mask must match */
305
                if ((res->flags ^ r->flags) & type_mask)
306
                        continue;
307
 
308
                /* Ok, try it out.. */
309
                if (allocate_resource(r, res, size, min, -1, size, NULL, NULL) < 0)
310
                        continue;
311
 
312
                /* PCI config space updated by caller.  */
313
                return 0;
314
        }
315
        return -EBUSY;
316
}
317
 
318
int pci_assign_resource(struct pci_dev *pdev, int resource)
319
{
320
        struct pcidev_cookie *pcp = pdev->sysdata;
321
        struct pci_pbm_info *pbm = pcp->pbm;
322
        struct resource *res = &pdev->resource[resource];
323
        unsigned long min, size;
324
        int err;
325
 
326
        if (res->flags & IORESOURCE_IO)
327
                min = pbm->io_space.start + 0x400UL;
328
        else
329
                min = pbm->mem_space.start;
330
 
331
        size = res->end - res->start + 1;
332
 
333
        err = pci_assign_bus_resource(pdev->bus, pdev, res, size, min, resource);
334
 
335
        if (err < 0) {
336
                printk("PCI: Failed to allocate resource %d for %s\n",
337
                       resource, pdev->name);
338
        } else {
339
                /* Update PCI config space. */
340
                pbm->parent->base_address_update(pdev, resource);
341
        }
342
 
343
        return err;
344
}
345
 
346
void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
347
                             struct resource *res2, int index)
348
{
349
}
350
 
351
void pcibios_update_irq(struct pci_dev *pdev, int irq)
352
{
353
}
354
 
355
void pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
356
                               struct pbus_set_ranges_data *pranges)
357
{
358
}
359
 
360
void pcibios_align_resource(void *data, struct resource *res,
361
                            unsigned long size, unsigned long align)
362
{
363
}
364
 
365
int pcibios_enable_device(struct pci_dev *pdev, int mask)
366
{
367
        return 0;
368
}
369
 
370
char * __init pcibios_setup(char *str)
371
{
372
        if (!strcmp(str, "onboardfirst")) {
373
                pci_device_reorder = 1;
374
                return NULL;
375
        }
376
        if (!strcmp(str, "noreorder")) {
377
                pci_device_reorder = 0;
378
                return NULL;
379
        }
380
        return str;
381
}
382
 
383
/* Platform support for /proc/bus/pci/X/Y mmap()s. */
384
 
385
/* If the user uses a host-bridge as the PCI device, he may use
386
 * this to perform a raw mmap() of the I/O or MEM space behind
387
 * that controller.
388
 *
389
 * This can be useful for execution of x86 PCI bios initialization code
390
 * on a PCI card, like the xfree86 int10 stuff does.
391
 */
392
static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma,
393
                                      enum pci_mmap_state mmap_state)
394
{
395
        struct pcidev_cookie *pcp = pdev->sysdata;
396
        struct pci_pbm_info *pbm;
397
        struct pci_controller_info *p;
398
        unsigned long space_size, user_offset, user_size;
399
 
400
        if (!pcp)
401
                return -ENXIO;
402
        pbm = pcp->pbm;
403
        if (!pbm)
404
                return -ENXIO;
405
 
406
        p = pbm->parent;
407
        if (p->pbms_same_domain) {
408
                unsigned long lowest, highest;
409
 
410
                lowest = ~0UL; highest = 0UL;
411
                if (mmap_state == pci_mmap_io) {
412
                        if (p->pbm_A.io_space.flags) {
413
                                lowest = p->pbm_A.io_space.start;
414
                                highest = p->pbm_A.io_space.end + 1;
415
                        }
416
                        if (p->pbm_B.io_space.flags) {
417
                                if (lowest > p->pbm_B.io_space.start)
418
                                        lowest = p->pbm_B.io_space.start;
419
                                if (highest < p->pbm_B.io_space.end + 1)
420
                                        highest = p->pbm_B.io_space.end + 1;
421
                        }
422
                        space_size = highest - lowest;
423
                } else {
424
                        if (p->pbm_A.mem_space.flags) {
425
                                lowest = p->pbm_A.mem_space.start;
426
                                highest = p->pbm_A.mem_space.end + 1;
427
                        }
428
                        if (p->pbm_B.mem_space.flags) {
429
                                if (lowest > p->pbm_B.mem_space.start)
430
                                        lowest = p->pbm_B.mem_space.start;
431
                                if (highest < p->pbm_B.mem_space.end + 1)
432
                                        highest = p->pbm_B.mem_space.end + 1;
433
                        }
434
                        space_size = highest - lowest;
435
                }
436
        } else {
437
                if (mmap_state == pci_mmap_io) {
438
                        space_size = (pbm->io_space.end -
439
                                      pbm->io_space.start) + 1;
440
                } else {
441
                        space_size = (pbm->mem_space.end -
442
                                      pbm->mem_space.start) + 1;
443
                }
444
        }
445
 
446
        /* Make sure the request is in range. */
447
        user_offset = vma->vm_pgoff << PAGE_SHIFT;
448
        user_size = vma->vm_end - vma->vm_start;
449
 
450
        if (user_offset >= space_size ||
451
            (user_offset + user_size) > space_size)
452
                return -EINVAL;
453
 
454
        if (p->pbms_same_domain) {
455
                unsigned long lowest = ~0UL;
456
 
457
                if (mmap_state == pci_mmap_io) {
458
                        if (p->pbm_A.io_space.flags)
459
                                lowest = p->pbm_A.io_space.start;
460
                        if (p->pbm_B.io_space.flags &&
461
                            lowest > p->pbm_B.io_space.start)
462
                                lowest = p->pbm_B.io_space.start;
463
                } else {
464
                        if (p->pbm_A.mem_space.flags)
465
                                lowest = p->pbm_A.mem_space.start;
466
                        if (p->pbm_B.mem_space.flags &&
467
                            lowest > p->pbm_B.mem_space.start)
468
                                lowest = p->pbm_B.mem_space.start;
469
                }
470
                vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT;
471
        } else {
472
                if (mmap_state == pci_mmap_io) {
473
                        vma->vm_pgoff = (pbm->io_space.start +
474
                                         user_offset) >> PAGE_SHIFT;
475
                } else {
476
                        vma->vm_pgoff = (pbm->mem_space.start +
477
                                         user_offset) >> PAGE_SHIFT;
478
                }
479
        }
480
 
481
        return 0;
482
}
483
 
484
/* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding
485
 * to the 32-bit pci bus offset for DEV requested by the user.
486
 *
487
 * Basically, the user finds the base address for his device which he wishes
488
 * to mmap.  They read the 32-bit value from the config space base register,
489
 * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
490
 * offset parameter of mmap on /proc/bus/pci/XXX for that device.
491
 *
492
 * Returns negative error code on failure, zero on success.
493
 */
494
static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
495
                                  enum pci_mmap_state mmap_state)
496
{
497
        unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT;
498
        unsigned long user32 = user_offset & pci_memspace_mask;
499
        unsigned long largest_base, this_base, addr32;
500
        int i;
501
 
502
        if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
503
                return __pci_mmap_make_offset_bus(dev, vma, mmap_state);
504
 
505
        /* Figure out which base address this is for. */
506
        largest_base = 0UL;
507
        for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
508
                struct resource *rp = &dev->resource[i];
509
 
510
                /* Active? */
511
                if (!rp->flags)
512
                        continue;
513
 
514
                /* Same type? */
515
                if (i == PCI_ROM_RESOURCE) {
516
                        if (mmap_state != pci_mmap_mem)
517
                                continue;
518
                } else {
519
                        if ((mmap_state == pci_mmap_io &&
520
                             (rp->flags & IORESOURCE_IO) == 0) ||
521
                            (mmap_state == pci_mmap_mem &&
522
                             (rp->flags & IORESOURCE_MEM) == 0))
523
                                continue;
524
                }
525
 
526
                this_base = rp->start;
527
 
528
                addr32 = (this_base & PAGE_MASK) & pci_memspace_mask;
529
 
530
                if (mmap_state == pci_mmap_io)
531
                        addr32 &= 0xffffff;
532
 
533
                if (addr32 <= user32 && this_base > largest_base)
534
                        largest_base = this_base;
535
        }
536
 
537
        if (largest_base == 0UL)
538
                return -EINVAL;
539
 
540
        /* Now construct the final physical address. */
541
        if (mmap_state == pci_mmap_io)
542
                vma->vm_pgoff = (((largest_base & ~0xffffffUL) | user32) >> PAGE_SHIFT);
543
        else
544
                vma->vm_pgoff = (((largest_base & ~(pci_memspace_mask)) | user32) >> PAGE_SHIFT);
545
 
546
        return 0;
547
}
548
 
549
/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
550
 * mapping.
551
 */
552
static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
553
                                            enum pci_mmap_state mmap_state)
554
{
555
        vma->vm_flags |= (VM_SHM | VM_LOCKED);
556
}
557
 
558
/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
559
 * device mapping.
560
 */
561
static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
562
                                             enum pci_mmap_state mmap_state)
563
{
564
        /* Our io_remap_page_range takes care of this, do nothing. */
565
}
566
 
567
extern int io_remap_page_range(unsigned long from, unsigned long offset,
568
                               unsigned long size, pgprot_t prot, int space);
569
 
570
/* Perform the actual remap of the pages for a PCI device mapping, as appropriate
571
 * for this architecture.  The region in the process to map is described by vm_start
572
 * and vm_end members of VMA, the base physical address is found in vm_pgoff.
573
 * The pci device structure is provided so that architectures may make mapping
574
 * decisions on a per-device or per-bus basis.
575
 *
576
 * Returns a negative error code on failure, zero on success.
577
 */
578
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
579
                        enum pci_mmap_state mmap_state,
580
                        int write_combine)
581
{
582
        int ret;
583
 
584
        ret = __pci_mmap_make_offset(dev, vma, mmap_state);
585
        if (ret < 0)
586
                return ret;
587
 
588
        __pci_mmap_set_flags(dev, vma, mmap_state);
589
        __pci_mmap_set_pgprot(dev, vma, mmap_state);
590
 
591
        ret = io_remap_page_range(vma->vm_start,
592
                                  (vma->vm_pgoff << PAGE_SHIFT |
593
                                   (write_combine ? 0x1UL : 0x0UL)),
594
                                  vma->vm_end - vma->vm_start, vma->vm_page_prot, 0);
595
        if (ret)
596
                return ret;
597
 
598
        vma->vm_flags |= VM_IO;
599
        return 0;
600
}
601
 
602
/* Return the index of the PCI controller for device PDEV. */
603
 
604
int pci_controller_num(struct pci_dev *pdev)
605
{
606
        struct pcidev_cookie *cookie = pdev->sysdata;
607
        int ret;
608
 
609
        if (cookie != NULL) {
610
                struct pci_pbm_info *pbm = cookie->pbm;
611
                if (pbm == NULL || pbm->parent == NULL) {
612
                        ret = -ENXIO;
613
                } else {
614
                        struct pci_controller_info *p = pbm->parent;
615
 
616
                        ret = p->index;
617
                        if (p->pbms_same_domain == 0)
618
                                ret = ((ret << 1) +
619
                                       ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
620
                }
621
        } else {
622
                ret = -ENXIO;
623
        }
624
 
625
        return ret;
626
}
627
 
628
#endif /* !(CONFIG_PCI) */

powered by: WebSVN 2.1.0

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