source: rtems/cpukit/libpci/pci_cfg_auto.c @ 1f4f1e2e

4.11
Last change on this file since 1f4f1e2e was 1f4f1e2e, checked in by Daniel Hellstrom <daniel@…>, on Apr 8, 2015 at 8:39:41 AM

LIBPCI: various comment/unsed clean-ups

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