source: rtems/cpukit/libpci/pci_cfg_auto.c @ c1c37a1

4.115
Last change on this file since c1c37a1 was c1c37a1, checked in by Daniel Hellstrom <daniel@…>, on 04/07/15 at 12:25:49

LIBPCI: converted to BSD header

  • Property mode set to 100644
File size: 26.7 KB
Line 
1/*  PCI (Auto) configuration Library. Setup PCI configuration space and IRQ.
2 *
3 *  COPYRIGHT (c) 2010 Cobham Gaisler AB.
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 */
9
10#include <rtems.h>
11#include <stdlib.h>
12#include <rtems/bspIo.h>
13#include <string.h>
14
15/* Configure headers */
16#define PCI_CFG_AUTO_LIB
17
18#include <pci.h>
19#include <pci/access.h>
20#include <pci/cfg.h>
21
22/* Define PCI_INFO_ON_STARTUP to get a listing of configured devices at boot
23 * time
24 */
25#undef PCI_INFO_ON_STARTUP
26
27/* #define DEBUG */
28
29#ifdef DEBUG
30#define DBG(x...) printk(x)
31#else
32#define DBG(x...)
33#endif
34
35/* PCI Library
36 * (For debugging it might be good to use other functions or the driver's
37 *  directly)
38 */
39#define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
40#define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
41#define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
42#define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
43#define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
44#define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
45
46/* Number of PCI buses */
47extern int pci_bus_cnt;
48
49int pci_config_auto_initialized = 0;
50
51/* Configuration setup */
52struct pci_auto_setup pci_auto_cfg;
53
54/* Insert BAR into the sorted resources list. The BARs are sorted on the
55 * BAR size/alignment need.
56 */
57static void pci_res_insert(struct pci_res **root, struct pci_res *res)
58{
59        struct pci_res *curr, *last;
60        unsigned long curr_size_resulting_boundary, size_resulting_boundary;
61        unsigned long boundary, size;
62
63        res->start = 0;
64        res->end = 0;
65        boundary = res->boundary;
66        size = res->size;
67
68        /* Insert the resources depending on the boundary needs
69         * Normally the boundary=size of the BAR, however when
70         * PCI bridges are involved the bridge's boundary may be
71         * smaller that the size due to the fact that a bridge
72         * may have different-sized BARs behind, the largest BAR
73         * (also the BAR with the largest boundary) will decide
74         * the alignment need.
75         */
76        last = NULL;
77        curr = *root;
78
79        /* Order List after boundary, the boundary is maintained
80         * when the size is on an equal boundary, normally it is
81         * but may not be with bridges. So in second hand it is
82         * sorted after resulting boundary - the boundary after
83         * the resource.
84         */
85        while (curr && (curr->boundary >= boundary)) {
86                if (curr->boundary == boundary) {
87                        /* Find Resulting boundary of size */
88                        size_resulting_boundary = 1;
89                        while ((size & size_resulting_boundary) == 0)
90                                size_resulting_boundary =
91                                        size_resulting_boundary << 1;
92
93                        /* Find Resulting boundary of curr->size */
94                        curr_size_resulting_boundary = 1;
95                        while ((curr->size & curr_size_resulting_boundary) == 0)
96                                curr_size_resulting_boundary =
97                                        curr_size_resulting_boundary << 1;
98
99                        if (size_resulting_boundary >=
100                            curr_size_resulting_boundary)
101                                break;
102                }
103                last = curr;
104                curr = curr->next;
105        }
106
107        if (last == NULL) {
108                /* Insert first in list */
109                res->next = *root;
110                *root = res;
111        } else {
112                last->next = res;
113                res->next = curr;
114        }
115}
116
117#ifdef DEBUG
118void pci_res_list_print(struct pci_res *root)
119{
120        if (root == NULL)
121                return;
122
123        printf("RESOURCE LIST:\n");
124        while (root) {
125                printf(" SIZE: 0x%08x, BOUNDARY: 0x%08x\n", root->size,
126                                                                root->boundary);
127                root = root->next;
128        }
129}
130#endif
131
132/* Reorder a size/alignment ordered resources list. The idea is to
133 * avoid unused due to alignment/size restriction.
134 *
135 * NOTE: The first element is always untouched.
136 * NOTE: If less than three elements in list, nothing will be done
137 *
138 * Normally a BAR has the same alignment requirements as the size of the
139 * BAR. However, when bridges are invloved the alignment need may be smaller
140 * that the size, because a bridge resource consist or multiple BARs.
141 * For example, say that a bridge with a 256Mb and a 16Mb BAR is found, then
142 * the alignment is required to be 256Mb but the size 256+16Mb.
143 *
144 * In order to minimize dead space on the bus, the bounadry ordered list
145 * is reordered, example:
146 *  BUS0
147 *  |            BUS1
148 *  |------------|
149 *  |            |-- BAR0: SIZE=256Mb, ALIGNMENT=256MB
150 *  |            |-- BAR1: SIZE=16Mb, ALIGNMENT=16MB
151 *  |            |
152 *  |            |
153 *  |            |
154 *  |            |          BUS2 (BAR_BRIDGE1: SIZE=256+16, ALIGNEMENT=256)
155 *  |            |----------|
156 *  |            |          |-- BAR2: SIZE=256Mb, ALIGNMENT=256Mb
157 *  |            |          |-- BAR3: SIZE=16Mb, ALIGNMENT=16MB
158 *
159 * A alignement/boundary ordered list of BUS1 will look like:
160 *      - BAR_BRIDGE1
161 *      - BAR0            (ALIGMENT NEED 256Mb)
162 *      - BAR1
163 *
164 * However, Between BAR_BRIDGE1 and BAR0 will be a unused hole of 256-16Mb.
165 * We can put BAR1 before BAR0 to avoid the problem.
166 */
167static void pci_res_reorder(struct pci_res *root)
168{
169        struct pci_res *curr, *last, *curr2, *last2;
170        unsigned int start, start_next, hole_size, hole_boundary;
171
172        if (root == NULL)
173                return;
174
175        /* Make up a start address with the boundary of the
176         * First element.
177         */
178        start = root->boundary + root->size;
179        last = root;
180        curr = root->next;
181        while (curr) {
182
183                /* Find start address of resource */
184                start_next = (start + (curr->boundary - 1)) &
185                                        ~(curr->boundary - 1);
186
187                /* Find hole size, the unsed space inbetween last resource
188                 *and next */
189                hole_size = start_next - start;
190
191                /* Find Boundary of START */
192                hole_boundary = 1;
193                while ((start & hole_boundary) == 0)
194                        hole_boundary = hole_boundary<<1;
195
196                /* Detect dead hole */
197                if (hole_size > 0) {
198                        /* Step through list and try to find a resource that
199                         * can fit into hole. Take into account hole start
200                         * boundary and hole size.
201                         */
202                        last2 = curr;
203                        curr2 = curr->next;
204                        while (curr2) {
205                                if ((curr2->boundary <= hole_boundary) &&
206                                         (curr2->size <= hole_size)) {
207                                        /* Found matching resource. Move it
208                                         * first in the hole. Then rescan, now
209                                         * that the hole has changed in
210                                         * size/boundary.
211                                         */
212                                        last2->next = curr2->next;
213                                        curr2->next = curr;
214                                        last->next = curr2;
215
216                                        /* New Start address */
217                                        start_next = (start +
218                                                     (curr2->boundary - 1)) &
219                                                     ~(curr2->boundary - 1);
220                                        /* Since we inserted the resource before
221                                         * curr we need to re-evaluate curr one
222                                         * more, more resources may fit into the
223                                         * shrunken hole.
224                                         */
225                                        curr = curr2;
226                                        break;
227                                }
228                                last2 = curr2;
229                                curr2 = curr2->next;
230                        }
231                }
232
233                /* No hole or nothing fitted into hole. */
234                start = start_next;
235
236                last = curr;
237                curr = curr->next;
238        }
239}
240
241/* Find the total size required in PCI address space needed by a resource list*/
242static unsigned int pci_res_size(struct pci_res *root)
243{
244        struct pci_res *curr;
245        unsigned int size;
246
247        /* Get total size of all resources */
248        size = 0;
249        curr = root;
250        while (curr) {
251                size = (size + (curr->boundary - 1)) & ~(curr->boundary - 1);
252                size += curr->size;
253                curr = curr->next;
254        }
255
256        return size;
257}
258
259#if 0 /* not used for now */
260/* Free a device and secondary bus if device is a bridge */
261static void pci_dev_free(struct pci_dev *dev)
262{
263        struct pci_dev *subdev;
264        struct pci_bus *bus;
265
266        if (dev->flags & PCI_DEV_BRIDGE) {
267                bus = (struct pci_bus *)dev;
268                for (subdev = bus->devs; subdev ; subdev = subdev->next)
269                        pci_dev_free(dev);
270        }
271
272        free(dev);
273}
274#endif
275
276static struct pci_dev *pci_dev_create(int isbus)
277{
278        void *ptr;
279        int size;
280
281        if (isbus)
282                size = sizeof(struct pci_bus);
283        else
284                size = sizeof(struct pci_dev);
285
286        ptr = malloc(size);
287        if (!ptr)
288                rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
289        memset(ptr, 0, size);
290        return ptr;
291}
292
293static void pci_find_devs(struct pci_bus *bus)
294{
295        uint32_t id, tmp;
296        uint8_t header;
297        int slot, func, fail;
298        struct pci_dev *dev, **listptr;
299        struct pci_bus *bridge;
300        pci_dev_t pcidev;
301
302        DBG("Scanning bus %d\n", bus->num);
303
304        listptr = &bus->devs;
305        for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
306
307                /* Slot address */
308                pcidev = PCI_DEV(bus->num, slot, 0);
309
310                for (func = 0; func <= PCI_FUNCMAX; func++, pcidev++) {
311
312                        fail = PCI_CFG_R32(pcidev, PCIR_VENDOR, &id);
313                        if (fail || id == 0xffffffff || id == 0) {
314                                /*
315                                 * This slot is empty
316                                 */
317                                if (func == 0)
318                                        break;
319                                else
320                                        continue;
321                        }
322
323                        DBG("Found PCIDEV 0x%x at (bus %x, slot %x, func %x)\n",
324                                                        id, bus, slot, func);
325
326                        /* Set command to reset values, it disables bus
327                         * mastering and address responses.
328                         */
329                        PCI_CFG_W16(pcidev, PCIR_COMMAND, 0);
330
331                        /* Clear any already set status bits */
332                        PCI_CFG_W16(pcidev, PCIR_STATUS, 0xf900);
333
334                        /* Set latency timer to 64 */
335                        PCI_CFG_W8(pcidev, PCIR_LATTIMER, 64);
336
337                        PCI_CFG_R32(pcidev, PCIR_REVID, &tmp);
338                        tmp >>= 16;
339                        dev = pci_dev_create(tmp == PCID_PCI2PCI_BRIDGE);
340                        *listptr = dev;
341                        listptr = &dev->next;
342
343                        dev->busdevfun = pcidev;
344                        dev->bus = bus;
345                        PCI_CFG_R16(pcidev, PCIR_VENDOR, &dev->vendor);
346                        PCI_CFG_R16(pcidev, PCIR_DEVICE, &dev->device);
347                        PCI_CFG_R32(pcidev, PCIR_REVID, &dev->classrev);
348
349                        if (tmp == PCID_PCI2PCI_BRIDGE) {
350                                DBG("Found PCI-PCI Bridge 0x%x at "
351                                    "(bus %x, slot %x, func %x)\n",
352                                    id, bus, slot, func);
353                                dev->flags = PCI_DEV_BRIDGE;
354                                dev->subvendor = 0;
355                                dev->subdevice = 0;
356                                bridge = (struct pci_bus *)dev;
357                                bridge->num = bus->sord + 1;
358                                bridge->pri = bus->num;
359                                bridge->sord = bus->sord + 1;
360
361                                /* Configure bridge (no support for 64-bit) */
362                                PCI_CFG_W32(pcidev, 0x28, 0);
363                                PCI_CFG_W32(pcidev, 0x2C, 0);
364                                tmp = (64 << 24) | (0xff << 16) |
365                                      (bridge->num << 8) | bridge->pri;
366                                PCI_CFG_W32(pcidev, PCIR_PRIBUS_1, tmp);
367
368                                /* Scan Secondary Bus */
369                                pci_find_devs(bridge);
370
371                                /* sord might have been updated */
372                                PCI_CFG_W8(pcidev, 0x1a, bridge->sord);
373                                bus->sord = bridge->sord;
374
375                                DBG("PCI-PCI BRIDGE: Primary %x, Secondary %x, "
376                                    "Subordinate %x\n",
377                                    bridge->pri, bridge->num, bridge->sord);
378                        } else {
379                                /* Disable Cardbus CIS Pointer */
380                                PCI_CFG_W32(pcidev, PCIR_CIS, 0);
381
382                                /* Devices have subsytem device and vendor ID */
383                                PCI_CFG_R16(pcidev, PCIR_SUBVEND_0,
384                                                        &dev->subvendor);
385                                PCI_CFG_R16(pcidev, PCIR_SUBDEV_0,
386                                                        &dev->subdevice);
387                        }
388
389                        /* Stop if not a multi-function device */
390                        if (func == 0) {
391                                pci_cfg_r8(pcidev, PCIR_HDRTYPE, &header);
392                                if ((header & PCIM_MFDEV) == 0)
393                                        break;
394                        }
395                }
396        }
397}
398
399static void pci_find_bar(struct pci_dev *dev, int bar)
400{
401        uint32_t size, disable, mask;
402        struct pci_res *res = &dev->resources[bar];
403        pci_dev_t pcidev = dev->busdevfun;
404        int ofs;
405#ifdef DEBUG
406        char *str;
407#define DBG_SET_STR(str, val) str = (val)
408#else
409#define DBG_SET_STR(str, val)
410#endif
411
412        DBG("Bus: %x, Slot: %x, function: %x, bar%d\n",
413                PCI_DEV_EXPAND(pcidev), bar);
414
415        res->bar = bar;
416        if (bar == DEV_RES_ROM) {
417                if (dev->flags & PCI_DEV_BRIDGE)
418                        ofs = PCIR_BIOS_1;
419                else
420                        ofs = PCIR_BIOS;
421                disable = 0; /* ROM BARs have a unique enable bit per BAR */
422        } else {
423                ofs = PCIR_BAR(0) + (bar << 2);
424                disable = pci_invalid_address;
425        }
426
427        PCI_CFG_W32(pcidev, ofs, 0xffffffff);
428        PCI_CFG_R32(pcidev, ofs, &size);
429        PCI_CFG_W32(pcidev, ofs, disable);
430
431        if (size == 0 || size == 0xffffffff)
432                return;
433        if (bar == DEV_RES_ROM) {
434                mask = PCIM_BIOS_ADDR_MASK;
435                DBG_SET_STR(str, "ROM");
436                if (dev->bus->flags & PCI_BUS_MEM)
437                        res->flags = PCI_RES_MEM;
438                else
439                        res->flags = PCI_RES_MEMIO;
440        } else if (((size & 0x1) == 0) && (size & 0x6)) {
441                /* unsupported Memory type */
442                PCI_CFG_W32(pcidev, ofs, 0);
443                return;
444        } else {
445                mask = ~0xf;
446                if (size & 0x1) {
447                        /* I/O */
448                        mask = ~0x3;
449                        res->flags = PCI_RES_IO;
450                        DBG_SET_STR(str, "I/O");
451                        if (size & 0xffff0000)
452                                res->flags |= PCI_RES_IO32;
453                        /* Limit size of I/O space to 256 byte */
454                        size |= 0xffffff00;
455                        if ((dev->bus->flags & PCI_BUS_IO) == 0) {
456                                res->flags |= PCI_RES_FAIL;
457                                dev->flags |= PCI_DEV_RES_FAIL;
458                        }
459                } else {
460                        /* Memory. We convert Prefetchable Memory BARs to Memory
461                         * BARs in case the Bridge does not support prefetchable
462                         * memory.
463                         */
464                        if ((size & 0x8) && (dev->bus->flags & PCI_BUS_MEM)) {
465                                /* Prefetchable and Bus supports it */
466                                res->flags = PCI_RES_MEM;
467                                DBG_SET_STR(str, "MEM");
468                        } else {
469                                res->flags = PCI_RES_MEMIO;
470                                DBG_SET_STR(str, "MEMIO");
471                        }
472                }
473        }
474        size &= mask;
475        res->size = ~size + 1;
476        res->boundary = ~size + 1;
477
478        DBG("Bus: %x, Slot: %x, function: %x, %s bar%d size: %x\n",
479                PCI_DEV_EXPAND(pcidev), str, bar, res->size);
480}
481
482static int pci_find_res_dev(struct pci_dev *dev, void *unused)
483{
484        struct pci_bus *bridge;
485        uint32_t tmp;
486        uint16_t tmp16;
487        pci_dev_t pcidev = dev->busdevfun;
488        int i, maxbars;
489
490        if (dev->flags & PCI_DEV_BRIDGE) {
491                /* PCI-PCI Bridge */
492                bridge = (struct pci_bus *)dev;
493
494                /* Only 2 Bridge BARs */
495                maxbars = 2;
496
497                /* Probe Bridge Spaces (MEMIO space always implemented), the
498                 * probe disables all space-decoding at the same time
499                 */
500                PCI_CFG_W32(pcidev, 0x30, 0);
501                PCI_CFG_W16(pcidev, 0x1c, 0x00f0);
502                PCI_CFG_R16(pcidev, 0x1c, &tmp16);
503                if (tmp16 != 0) {
504                        bridge->flags |= PCI_BUS_IO;
505                        if (tmp16 & 0x1)
506                                bridge->flags |= PCI_BUS_IO32;
507                }
508
509                PCI_CFG_W32(pcidev, 0x24, 0x0000ffff);
510                PCI_CFG_R32(pcidev, 0x24, &tmp);
511                if (tmp != 0)
512                        bridge->flags |= PCI_BUS_MEM;
513
514                PCI_CFG_W32(pcidev, 0x20, 0x0000ffff);
515                bridge->flags |= PCI_BUS_MEMIO;
516        } else {
517                /* Normal PCI Device as max 6 BARs */
518                maxbars = 6;
519        }
520
521        /* Probe BARs */
522        for (i = 0; i < maxbars; i++)
523                pci_find_bar(dev, i);
524        pci_find_bar(dev, DEV_RES_ROM);
525
526        return 0;
527}
528
529static int pci_add_res_dev(struct pci_dev *dev, void *arg);
530
531static void pci_add_res_bus(struct pci_bus *bus, int type)
532{
533        int tindex = type - 1;
534
535        /* Clear old resources */
536        bus->busres[tindex] = NULL;
537
538        /* Add resources of devices behind bridge if bridge supports
539         * resource type. If MEM space not supported by bridge, they are
540         * converted to MEMIO in the process.
541         */
542        if (!((type == PCI_BUS_IO) && ((bus->flags & PCI_BUS_IO) == 0))) {
543                pci_for_each_child(bus, pci_add_res_dev, (void *)type, 0);
544
545                /* Reorder Bus resources to fit more optimally (avoid dead
546                 * PCI space). Currently they are sorted by boundary and size.
547                 *
548                 * This is especially important when multiple buses (bridges)
549                 * are present.
550                 */
551                pci_res_reorder(bus->busres[tindex]);
552        }
553}
554
555static int pci_add_res_dev(struct pci_dev *dev, void *arg)
556{
557        int tindex, type = (int)arg;
558        struct pci_bus *bridge;
559        struct pci_res *res, *first_busres;
560        int i;
561        uint32_t bbound;
562
563        /* Type index in Bus resource */
564        tindex = type - 1;
565
566        if (dev->flags & PCI_DEV_BRIDGE) {
567                /* PCI-PCI Bridge. Add all sub-bus resources first */
568                bridge = (struct pci_bus *)dev;
569
570                /* Add all child device's resources to this type */
571                pci_add_res_bus(bridge, type);
572
573                /* Propagate the resources from child bus to BAR on
574                 * this bus, by adding a "fake" BAR per type.
575                 */
576                res = &bridge->dev.resources[BUS_RES_START + tindex];
577                res->bar = BUS_RES_START + tindex;
578                res->start = 0;
579                res->end = 0;
580                res->flags = 0; /* mark BAR resource not available */
581                first_busres = bridge->busres[tindex];
582                if (first_busres) {
583                        res->flags = type;
584                        res->size = pci_res_size(first_busres);
585                        res->boundary = first_busres->boundary;
586                        if (type == PCI_RES_IO) {
587                                bbound = 0x1000; /* Bridge I/O min 4KB */
588                        } else {
589                                bbound = 0x100000; /* Bridge MEM min 1MB */
590
591                                /* Convert MEM to MEMIO if not supported by
592                                 * this bridge
593                                 */
594                                if ((bridge->flags & PCI_BUS_MEM) == 0)
595                                        res->flags = PCI_RES_MEMIO;
596                        }
597                        /* Fulfil minimum bridge boundary */
598                        if (res->boundary < bbound)
599                                res->boundary = bbound;
600                        /* Make sure that size is atleast bridge boundary */
601                        if (res->size > bbound && (res->size & (bbound-1)))
602                                res->size = (res->size | (bbound-1)) + 1;
603                }
604        }
605
606        /* Normal PCI Device as max 6 BARs and a ROM Bar.
607         * Insert BARs into the sorted resource list.
608         */
609        for (i = 0; i < DEV_RES_CNT; i++) {
610                res = &dev->resources[i];
611                if ((res->flags & PCI_RES_TYPE_MASK) != type)
612                        continue;
613                pci_res_insert(&dev->bus->busres[tindex], res);
614        }
615
616        return 0;
617}
618
619/* Function assumes that base is properly aligned to the requirement of the
620 * largest BAR in the system.
621 */
622static uint32_t pci_alloc_res(struct pci_bus *bus, int type,
623                            uint32_t start, uint32_t end)
624{
625        struct pci_dev *dev;
626        struct pci_res *res, **prev_next;
627        unsigned long starttmp;
628        struct pci_bus *bridge;
629        int removed, sec_type;
630
631        /* The resources are sorted on their size (size and alignment is the
632         * same)
633         */
634        prev_next = &bus->busres[type - 1];
635        while ((res = *prev_next) != NULL) {
636
637                dev = RES2DEV(res);
638                removed = 0;
639
640                /* Align start to this reource's need, only needed after
641                 * a bridge resource has been allocated.
642                 */
643                starttmp = (start + (res->boundary-1)) & ~(res->boundary-1);
644
645                if ((starttmp + res->size - 1) > end) {
646                        /* Not enough memory available for this resource */
647                        printk("PCI[%x:%x:%x]: DEV BAR%d (%d): no resource "
648                               "assigned\n",
649                               PCI_DEV_EXPAND(dev->busdevfun),
650                               res->bar, res->flags & PCI_RES_TYPE_MASK);
651                        res->start = res->end = 0;
652
653                        /* If this resources is a bridge window to the
654                         * secondary bus, the secondary resources are not
655                         * changed which has the following effect:
656                         *  I/O    :  Will never be assigned
657                         *  MEMIO  :  Will never be assigned
658                         *  MEM    :  Will stay marked as MEM, but bridge window
659                         *            is changed into MEMIO, when the window is
660                         *            assigned a MEMIO address the secondary
661                         *            resources will also be assigned.
662                         */
663
664                        if (type == PCI_RES_MEM) {
665                                /* Try prefetchable as non-prefetchable mem */
666                                res->flags &= ~PCI_RES_MEM_PREFETCH;
667                                /* Remove resource from MEM list, ideally we
668                                 * should regenerate this list in order to fit
669                                 * the comming BARs more optimially...
670                                 */
671                                *prev_next = res->next;
672                                /* We should not update prev_next here since
673                                 * we just removed the resource from the list
674                                 */
675                                removed = 1;
676                        } else {
677                                res->flags |= PCI_RES_FAIL;
678                                dev->flags |= PCI_DEV_RES_FAIL;
679                        }
680                } else {
681                        start = starttmp;
682
683                        res->start = start;
684                        res->end = start + res->size;
685
686                        /* "Virtual BAR" on a bridge? A bridge resource need all
687                         * its child devices resources allocated
688                         */
689                        if ((res->bar != DEV_RES_ROM) &&
690                            (dev->flags & PCI_DEV_BRIDGE) &&
691                            (res->bar >= BUS_RES_START)) {
692                                bridge = (struct pci_bus *)dev;
693                                /* If MEM bar was changed into a MEMIO the
694                                 * secondary MEM resources are still set to MEM,
695                                 */
696                                if (type == PCI_BUS_MEMIO &&
697                                    res->bar == BRIDGE_RES_MEM)
698                                        sec_type = PCI_RES_MEM;
699                                else
700                                        sec_type = type;
701
702                                pci_alloc_res(bridge, sec_type, res->start,
703                                                res->end);
704                        }
705
706                        start += res->size;
707                }
708                if (removed == 0)
709                        prev_next = &res->next;
710        }
711
712        return start;
713}
714
715static void pci_set_bar(struct pci_dev *dev, int residx)
716{
717        uint32_t tmp;
718        uint16_t tmp16;
719        pci_dev_t pcidev;
720        struct pci_res *res;
721        int is_bridge, ofs;
722
723        res = &dev->resources[residx];
724        pcidev = dev->busdevfun;
725
726        if ((res->flags == 0) || (res->flags & PCI_RES_FAIL))
727                return;
728
729        is_bridge = dev->flags & PCI_DEV_BRIDGE;
730
731        if (res->bar == DEV_RES_ROM) {
732                /* ROM: 32-bit prefetchable memory BAR */
733                if (is_bridge)
734                        ofs = PCIR_BIOS_1;
735                else
736                        ofs = PCIR_BIOS;
737                PCI_CFG_W32(pcidev, ofs, res->start | PCIM_BIOS_ENABLE);
738                DBG("PCI[%x:%x:%x]: ROM BAR: 0x%x-0x%x\n",
739                        PCI_DEV_EXPAND(pcidev), res->start, res->end);
740        } else if (is_bridge && (res->bar == BRIDGE_RES_IO)) {
741                /* PCI Bridge I/O BAR */
742                DBG("PCI[%x:%x:%x]: BAR 1C: 0x%x-0x%x\n",
743                        PCI_DEV_EXPAND(pcidev), res->start, res->end);
744
745                /* Limit and Base */
746                tmp16 = ((res->end-1) & 0x0000f000) |
747                        ((res->start & 0x0000f000) >> 8);
748                tmp = ((res->end-1) & 0xffff0000) | (res->start >> 16);
749
750                DBG("PCI[%x:%x:%x]: BRIDGE BAR 0x%x: 0x%08x [0x30: 0x%x]\n",
751                        PCI_DEV_EXPAND(pcidev), 0x1C, tmp, tmp2);
752                PCI_CFG_W16(pcidev, 0x1C, tmp16);
753                PCI_CFG_W32(pcidev, 0x30, tmp);
754        } else if (is_bridge && (res->bar >= BRIDGE_RES_MEMIO)) {
755                /* PCI Bridge MEM and MEMIO Space */
756
757                /* Limit and Base */
758                tmp = ((res->end-1) & 0xfff00000) | (res->start >> 16);
759
760                DBG("PCI[%x:%x:%x]: BRIDGE BAR 0x%x: 0x%08x\n",
761                        PCI_DEV_EXPAND(pcidev),
762                        0x20 + (res->bar-BRIDGE_RES_MEMIO)*4, tmp);
763                PCI_CFG_W32(pcidev, 0x20+(res->bar-BRIDGE_RES_MEMIO)*4, tmp);
764        } else {
765                /* PCI Device */
766                DBG("PCI[%x:%x:%x]: DEV BAR%d: 0x%08x\n",
767                        PCI_DEV_EXPAND(pcidev), res->bar, res->start);
768                ofs = PCIR_BAR(0) + res->bar*4;
769                PCI_CFG_W32(pcidev, ofs, res->start);
770        }
771
772        /* Enable Memory or I/O responses */
773        if ((res->flags & PCI_RES_TYPE_MASK) == PCI_RES_IO)
774                pci_io_enable(pcidev);
775        else
776                pci_mem_enable(pcidev);
777
778        /* Enable Master if bridge */
779        if (is_bridge)
780                pci_master_enable(pcidev);
781}
782
783static int pci_set_res_dev(struct pci_dev *dev, void *unused)
784{
785        int i, maxbars;
786
787        if (dev->flags & PCI_DEV_BRIDGE)
788                maxbars = 2 + 3; /* 2 BARs + 3 Bridge-Windows "Virtual BARs" */
789        else
790                maxbars = 6; /* Normal PCI Device as max 6 BARs. */
791
792        /* Set BAR resources with previous allocated values */
793        for (i = 0; i < maxbars; i++)
794                pci_set_bar(dev, i);
795        pci_set_bar(dev, DEV_RES_ROM);
796
797        return 0;
798}
799
800/* Route IRQ through PCI-PCI Bridges */
801static int pci_route_irq(pci_dev_t dev, int irq_pin)
802{
803        int slot_grp;
804
805        if (PCI_DEV_BUS(dev) == 0)
806                return irq_pin;
807
808        slot_grp = PCI_DEV_SLOT(dev) & 0x3;
809
810        return (((irq_pin - 1) + slot_grp) & 0x3) + 1;
811}
812
813/* Put assigned system IRQ into PCI interrupt line information field.
814 * This is to make it possible for drivers to read system IRQ / Vector from
815 * configuration space later on.
816 *
817 * 1. Get Interrupt PIN
818 * 2. Route PIN to host bridge
819 * 3. Get System interrupt number assignment for PIN
820 * 4. Set Interrupt LINE
821 */
822static int pci_set_irq_dev(struct pci_dev *dev, void *cfg)
823{
824        struct pci_auto_setup *autocfg = cfg;
825        uint8_t irq_pin, irq_line, *psysirq;
826        pci_dev_t pcidev;
827
828        psysirq = &dev->sysirq;
829        pcidev = dev->busdevfun;
830        PCI_CFG_R8(pcidev, PCIR_INTPIN, &irq_pin);
831
832        /* perform IRQ routing until we reach host bridge */
833        while (dev->bus && irq_pin != 0) {
834                irq_pin = autocfg->irq_route(dev->busdevfun, irq_pin);
835                dev = &dev->bus->dev;
836        }
837
838        /* Get IRQ from PIN on PCI bus0 */
839        if (irq_pin != 0 && autocfg->irq_map)
840                irq_line = autocfg->irq_map(dev->busdevfun, irq_pin);
841        else
842                irq_line = 0;
843
844        *psysirq = irq_line;
845
846        /* Set System Interrupt/Vector for device. 0 means no-IRQ */
847        PCI_CFG_W8(pcidev, PCIR_INTLINE, irq_line);
848
849        return 0;
850}
851
852/* This routine assumes that PCI access library has been successfully
853 * initialized. All information about the PCI bus needed is found in
854 * the argument.
855 *
856 * The PCI buses are enumerated as bridges are found, PCI devices are
857 * setup with BARs and IRQs, etc.
858 */
859int pci_config_auto(void)
860{
861        uint32_t end;
862        uint32_t startmemio, startmem, startio;
863        struct pci_auto_setup *autocfg = &pci_auto_cfg;
864#ifdef DEBUG
865        uint32_t endmemio, endmem, endio;
866        uint32_t start;
867#endif
868
869        if (pci_config_auto_initialized == 0)
870                return -1; /* no config given to library */
871
872#ifdef DEBUG
873        DBG("\n--- PCI MEMORY AVAILABLE ---\n");
874        if (autocfg->mem_size) {
875                start = autocfg->mem_start;
876                end = autocfg->mem_start + autocfg->mem_size - 1;
877                DBG(" MEM AVAIL [0x%08x-0x%08x]\n", start, end);
878        } else {
879                /* One big memory space */
880                DBG(" MEM share the space with MEMIO\n");
881        }
882        /* no-prefetchable memory space need separate memory space.
883         * For example PCI controller maps this region non-cachable.
884         */
885        start = autocfg->memio_start;
886        end = autocfg->memio_start + autocfg->memio_size - 1;
887        DBG(" MEMIO AVAIL [0x%08x-0x%08x]\n", start, end);
888        if (autocfg->io_size) {
889                start = autocfg->io_start;
890                end = autocfg->io_start + autocfg->io_size - 1;
891                DBG(" I/O AVAIL [0x%08x-0x%08x]\n", start, end);
892        } else {
893                DBG(" I/O Space not available\n");
894        }
895#endif
896
897        /* Init Host-Bridge */
898        memset(&pci_hb, 0, sizeof(pci_hb));
899        pci_hb.dev.flags = PCI_DEV_BRIDGE;
900        if (autocfg->memio_size <= 0)
901                return -1;
902        pci_hb.flags = PCI_BUS_MEMIO;
903        if (autocfg->mem_size)
904                pci_hb.flags |= PCI_BUS_MEM;
905        if (autocfg->io_size)
906                pci_hb.flags |= PCI_BUS_IO;
907
908        /* Find all PCI devices/functions on all buses. The buses will be
909         * enumrated (assigned a unique PCI Bus ID 0..255).
910         */
911        DBG("\n--- PCI SCANNING ---\n");
912        pci_find_devs(&pci_hb);
913        pci_bus_cnt = pci_hb.sord + 1;
914        if (pci_hb.devs == NULL)
915                return 0;
916
917        pci_system_type = PCI_SYSTEM_HOST;
918
919        /* Find all resources (MEM/MEMIO/IO BARs) of all devices/functions
920         * on all buses.
921         *
922         * Device resources behind bridges which does not support prefetchable
923         * memory are already marked as non-prefetchable memory.
924         * Devices which as I/O resources behind a bridge that do not support
925         * I/O space are marked DISABLED.
926         *
927         * All BARs and Bridge Spaces are disabled after this. Only the ones
928         * that are allocated an address are initilized later on.
929         */
930        DBG("\n\n--- PCI RESOURCES ---\n");
931        pci_for_each_dev(pci_find_res_dev, 0);
932
933        /* Add all device's resources to bus and sort them to fit in the PCI
934         * Window. The device resources are propagated upwards through bridges
935         * by adding a "virtual" BAR (boundary != BAR size).
936         *
937         * We wait with MEMIO (non-prefetchable memory) resources to after MEM
938         * resources have been allocated, so that MEM resources can be changed
939         * into MEMIO resources if not enough space.
940         */
941        pci_add_res_bus(&pci_hb, PCI_RES_IO);
942        pci_add_res_bus(&pci_hb, PCI_RES_MEM);
943
944        /* Start assigning found resource according to the sorted order. */
945
946        /* Allocate resources to I/O areas */
947        if (pci_hb.busres[BUS_RES_IO]) {
948                startio = autocfg->io_start;
949                end = startio + autocfg->io_size;
950#ifdef DEBUG
951                endio =
952#endif
953                        pci_alloc_res(&pci_hb, PCI_RES_IO, startio, end);
954        }
955
956        /* Allocate resources to prefetchable memory */
957        if (pci_hb.busres[BUS_RES_MEM]) {
958                startmem = autocfg->mem_start;
959                end = startmem + autocfg->mem_size;
960#ifdef DEBUG
961                endmem =
962#endif
963                        pci_alloc_res(&pci_hb, PCI_RES_MEM, startmem, end);
964        }
965
966        /* Add non-prefetchable memory resources and not fitting prefetchable
967         * memory resources.
968         *
969         * Some prefetchable memory resources may not have fitted into PCI
970         * window. Prefetchable memory can be mapped into non-prefetchable
971         * memory window. The failing BARs have been marked as MEMIO instead.
972         */
973        pci_add_res_bus(&pci_hb, PCI_RES_MEMIO);
974
975        /* Allocate resources to non-prefetchable memory */
976        if (pci_hb.busres[BUS_RES_MEMIO]) {
977                startmemio = autocfg->memio_start;
978                end = startmemio + autocfg->memio_size;
979#ifdef DEBUG
980                endmemio =
981#endif
982                        pci_alloc_res(&pci_hb, PCI_RES_MEMIO, startmemio, end);
983        }
984
985        DBG("\n--- PCI ALLOCATED SPACE RANGES ---\n");
986        DBG(" MEM NON-PREFETCHABLE: [0x%08x-0x%08x]\n", startmemio, endmemio);
987        DBG(" MEM PREFETCHABLE:     [0x%08x-0x%08x]\n", startmem, endmem);
988        DBG(" I/O:                  [0x%08x-0x%08x]\n", startio, endio);
989
990        /* Set all allocated BARs and Bridge Windows */
991        pci_for_each_dev(pci_set_res_dev, NULL);
992
993        /* Initialize IRQs of all devices. According to the PCI-PCI bridge
994         * specification the IRQs are routed differently depending on slot
995         * number. Drivers can override the default routing if a motherboard
996         * requires it.
997         */
998        if ((autocfg->options & CFGOPT_NOSETUP_IRQ) == 0) {
999                if (autocfg->irq_route == NULL) /* use standard irq routing */
1000                        autocfg->irq_route = pci_route_irq;
1001                pci_for_each_dev(pci_set_irq_dev, autocfg);
1002        }
1003
1004        DBG("PCI resource allocation done\n");
1005
1006        return 0;
1007}
1008
1009void pci_config_auto_register(void *config)
1010{
1011        pci_config_auto_initialized = 1;
1012        memcpy(&pci_auto_cfg, config, sizeof(struct pci_auto_setup));
1013}
Note: See TracBrowser for help on using the repository browser.