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

4.11
Last change on this file since a31845f7 was a31845f7, checked in by Daniel Hellstrom <daniel@…>, on Nov 28, 2011 at 9:11:10 AM

LIBPCI: added PCI layer to cpukit/libpci

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