Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:20

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  PCI (Auto) configuration Library. Setup PCI configuration space and IRQ.
0004  *
0005  *  COPYRIGHT (c) 2010 Cobham Gaisler AB.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 #include <rtems.h>
0030 #include <stdlib.h>
0031 #include <rtems/bspIo.h>
0032 #include <string.h>
0033 
0034 /* Configure headers */
0035 #define PCI_CFG_AUTO_LIB
0036 
0037 #include <pci.h>
0038 #include <pci/access.h>
0039 #include <pci/cfg.h>
0040 
0041 #include "pci_internal.h"
0042 
0043 /* #define DEBUG */
0044 
0045 #ifdef DEBUG
0046 #define DBG(x...) printk(x)
0047 #else
0048 #define DBG(x...)
0049 #endif
0050 
0051 /* PCI Library
0052  * (For debugging it might be good to use other functions or the driver's
0053  *  directly)
0054  */
0055 #define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
0056 #define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
0057 #define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
0058 #define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
0059 #define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
0060 #define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
0061 
0062 int pci_config_auto_initialized = 0;
0063 
0064 /* Configuration setup */
0065 struct pci_auto_setup pci_auto_cfg;
0066 
0067 /* Insert BAR into the sorted resources list. The BARs are sorted on the
0068  * BAR size/alignment need.
0069  */
0070 static void pci_res_insert(struct pci_res **root, struct pci_res *res)
0071 {
0072     struct pci_res *curr, *last;
0073     unsigned long curr_size_resulting_boundary, size_resulting_boundary;
0074     unsigned long boundary, size;
0075 
0076     res->start = 0;
0077     res->end = 0;
0078     boundary = res->boundary;
0079     size = res->size;
0080 
0081     /* Insert the resources depending on the boundary needs
0082      * Normally the boundary=size of the BAR, however when
0083      * PCI bridges are involved the bridge's boundary may be
0084      * smaller than the size due to the fact that a bridge
0085      * may have different-sized BARs behind, the largest BAR
0086      * (also the BAR with the largest boundary) will decide
0087      * the alignment need.
0088      */
0089     last = NULL;
0090     curr = *root;
0091 
0092     /* Order List after boundary, the boundary is maintained
0093      * when the size is on an equal boundary, normally it is
0094      * but may not be with bridges. So in second hand it is
0095      * sorted after resulting boundary - the boundary after
0096      * the resource.
0097      */
0098     while (curr && (curr->boundary >= boundary)) {
0099         if (curr->boundary == boundary) {
0100             /* Find Resulting boundary of size */
0101             size_resulting_boundary = 1;
0102             while ((size & size_resulting_boundary) == 0)
0103                 size_resulting_boundary =
0104                     size_resulting_boundary << 1;
0105 
0106             /* Find Resulting boundary of curr->size */
0107             curr_size_resulting_boundary = 1;
0108             while ((curr->size & curr_size_resulting_boundary) == 0)
0109                 curr_size_resulting_boundary =
0110                     curr_size_resulting_boundary << 1;
0111 
0112             if (size_resulting_boundary >=
0113                 curr_size_resulting_boundary)
0114                 break;
0115         }
0116         last = curr;
0117         curr = curr->next;
0118     }
0119 
0120     if (last == NULL) {
0121         /* Insert first in list */
0122         res->next = *root;
0123         *root = res;
0124     } else {
0125         last->next = res;
0126         res->next = curr;
0127     }
0128 }
0129 
0130 #ifdef DEBUG
0131 void pci_res_list_print(struct pci_res *root)
0132 {
0133     if (root == NULL)
0134         return;
0135 
0136     printf("RESOURCE LIST:\n");
0137     while (root) {
0138         printf(" SIZE: 0x%08x, BOUNDARY: 0x%08x\n", root->size,
0139                                 root->boundary);
0140         root = root->next;
0141     }
0142 }
0143 #endif
0144 
0145 /* Reorder a size/alignment ordered resources list. The idea is to
0146  * avoid unused due to alignment/size restriction.
0147  *
0148  * NOTE: The first element is always untouched.
0149  * NOTE: If less than three elements in list, nothing will be done
0150  *
0151  * Normally a BAR has the same alignment requirements as the size of the
0152  * BAR. However, when bridges are involved the alignment need may be smaller
0153  * than the size, because a bridge resource consist or multiple BARs.
0154  * For example, say that a bridge with a 256Mb and a 16Mb BAR is found, then
0155  * the alignment is required to be 256Mb but the size 256+16Mb.
0156  *
0157  * In order to minimize dead space on the bus, the boundary ordered list
0158  * is reordered, example:
0159  *  BUS0
0160  *  |            BUS1
0161  *  |------------|
0162  *  |            |-- BAR0: SIZE=256Mb, ALIGNMENT=256MB
0163  *  |            |-- BAR1: SIZE=16Mb, ALIGNMENT=16MB
0164  *  |            |
0165  *  |            |
0166  *  |            |
0167  *  |            |          BUS2 (BAR_BRIDGE1: SIZE=256+16, ALIGNEMENT=256)
0168  *  |            |----------|
0169  *  |            |          |-- BAR2: SIZE=256Mb, ALIGNMENT=256Mb
0170  *  |            |          |-- BAR3: SIZE=16Mb, ALIGNMENT=16MB
0171  *
0172  * A alignment/boundary ordered list of BUS1 will look like:
0173  *  - BAR_BRIDGE1
0174  *  - BAR0        (ALIGMENT NEED 256Mb)
0175  *  - BAR1
0176  *
0177  * However, Between BAR_BRIDGE1 and BAR0 will be a unused hole of 256-16Mb.
0178  * We can put BAR1 before BAR0 to avoid the problem.
0179  */
0180 static void pci_res_reorder(struct pci_res *root)
0181 {
0182     struct pci_res *curr, *last, *curr2, *last2;
0183     unsigned int start, start_next, hole_size, hole_boundary;
0184 
0185     if (root == NULL)
0186         return;
0187 
0188     /* Make up a start address with the boundary of the
0189      * First element.
0190      */
0191     start = root->boundary + root->size;
0192     last = root;
0193     curr = root->next;
0194     while (curr) {
0195 
0196         /* Find start address of resource */
0197         start_next = (start + (curr->boundary - 1)) &
0198                     ~(curr->boundary - 1);
0199 
0200         /* Find hole size, the unsed space in between last resource
0201          * and next */
0202         hole_size = start_next - start;
0203 
0204         /* Find Boundary of START */
0205         hole_boundary = 1;
0206         while ((start & hole_boundary) == 0)
0207             hole_boundary = hole_boundary<<1;
0208 
0209         /* Detect dead hole */
0210         if (hole_size > 0) {
0211             /* Step through list and try to find a resource that
0212              * can fit into hole. Take into account hole start
0213              * boundary and hole size.
0214              */
0215             last2 = curr;
0216             curr2 = curr->next;
0217             while (curr2) {
0218                 if ((curr2->boundary <= hole_boundary) &&
0219                      (curr2->size <= hole_size)) {
0220                     /* Found matching resource. Move it
0221                      * first in the hole. Then rescan, now
0222                      * that the hole has changed in
0223                      * size/boundary.
0224                      */
0225                     last2->next = curr2->next;
0226                     curr2->next = curr;
0227                     last->next = curr2;
0228 
0229                     /* New Start address */
0230                     start_next = (start +
0231                              (curr2->boundary - 1)) &
0232                              ~(curr2->boundary - 1);
0233                     /* Since we inserted the resource before
0234                      * curr we need to re-evaluate curr one
0235                      * more, more resources may fit into the
0236                      * shrunken hole.
0237                      */
0238                     curr = curr2;
0239                     break;
0240                 }
0241                 last2 = curr2;
0242                 curr2 = curr2->next;
0243             }
0244         }
0245 
0246         /* No hole or nothing fit into hole. */
0247         start = start_next;
0248 
0249         last = curr;
0250         curr = curr->next;
0251     }
0252 }
0253 
0254 /* Find the total size required in PCI address space needed by a resource list*/
0255 static unsigned int pci_res_size(struct pci_res *root)
0256 {
0257     struct pci_res *curr;
0258     unsigned int size;
0259 
0260     /* Get total size of all resources */
0261     size = 0;
0262     curr = root;
0263     while (curr) {
0264         size = (size + (curr->boundary - 1)) & ~(curr->boundary - 1);
0265         size += curr->size;
0266         curr = curr->next;
0267     }
0268 
0269     return size;
0270 }
0271 
0272 #if 0 /* not used for now */
0273 /* Free a device and secondary bus if device is a bridge */
0274 static void pci_dev_free(struct pci_dev *dev)
0275 {
0276     struct pci_dev *subdev;
0277     struct pci_bus *bus;
0278 
0279     if (dev->flags & PCI_DEV_BRIDGE) {
0280         bus = (struct pci_bus *)dev;
0281         for (subdev = bus->devs; subdev ; subdev = subdev->next)
0282             pci_dev_free(dev);
0283     }
0284 
0285     free(dev);
0286 }
0287 #endif
0288 
0289 static struct pci_dev *pci_dev_create(int isbus)
0290 {
0291     void *ptr;
0292     int size;
0293 
0294     if (isbus)
0295         size = sizeof(struct pci_bus);
0296     else
0297         size = sizeof(struct pci_dev);
0298 
0299     ptr = calloc(1, size);
0300     if (!ptr)
0301         rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
0302     return ptr;
0303 }
0304 
0305 static void pci_find_devs(struct pci_bus *bus)
0306 {
0307     uint32_t id, tmp;
0308     uint8_t header;
0309     int slot, func, fail;
0310     struct pci_dev *dev, **listptr;
0311     struct pci_bus *bridge;
0312     pci_dev_t pcidev;
0313 
0314     DBG("Scanning bus %d\n", bus->num);
0315 
0316     listptr = &bus->devs;
0317     for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
0318 
0319         /* Slot address */
0320         pcidev = PCI_DEV(bus->num, slot, 0);
0321 
0322         for (func = 0; func <= PCI_FUNCMAX; func++, pcidev++) {
0323 
0324             fail = PCI_CFG_R32(pcidev, PCIR_VENDOR, &id);
0325             if (fail || id == 0xffffffff || id == 0) {
0326                 /*
0327                  * This slot is empty
0328                  */
0329                 if (func == 0)
0330                     break;
0331                 else
0332                     continue;
0333             }
0334 
0335             DBG("Found PCIDEV 0x%x at (bus %x, slot %x, func %x)\n",
0336                             id, bus, slot, func);
0337 
0338             /* Set command to reset values, it disables bus
0339              * mastering and address responses.
0340              */
0341             PCI_CFG_W16(pcidev, PCIR_COMMAND, 0);
0342 
0343             /* Clear any already set status bits */
0344             PCI_CFG_W16(pcidev, PCIR_STATUS, 0xf900);
0345 
0346             /* Set latency timer to 64 */
0347             PCI_CFG_W8(pcidev, PCIR_LATTIMER, 64);
0348 
0349             PCI_CFG_R32(pcidev, PCIR_REVID, &tmp);
0350             tmp >>= 16;
0351             dev = pci_dev_create(tmp == PCID_PCI2PCI_BRIDGE);
0352             *listptr = dev;
0353             listptr = &dev->next;
0354 
0355             dev->busdevfun = pcidev;
0356             dev->bus = bus;
0357             PCI_CFG_R16(pcidev, PCIR_VENDOR, &dev->vendor);
0358             PCI_CFG_R16(pcidev, PCIR_DEVICE, &dev->device);
0359             PCI_CFG_R32(pcidev, PCIR_REVID, &dev->classrev);
0360 
0361             if (tmp == PCID_PCI2PCI_BRIDGE) {
0362                 DBG("Found PCI-PCI Bridge 0x%x at "
0363                     "(bus %x, slot %x, func %x)\n",
0364                     id, bus, slot, func);
0365                 dev->flags = PCI_DEV_BRIDGE;
0366                 dev->subvendor = 0;
0367                 dev->subdevice = 0;
0368                 bridge = (struct pci_bus *)dev;
0369                 bridge->num = bus->sord + 1;
0370                 bridge->pri = bus->num;
0371                 bridge->sord = bus->sord + 1;
0372 
0373                 /* Configure bridge (no support for 64-bit) */
0374                 PCI_CFG_W32(pcidev, 0x28, 0);
0375                 PCI_CFG_W32(pcidev, 0x2C, 0);
0376                 tmp = (64 << 24) | (0xff << 16) |
0377                       (bridge->num << 8) | bridge->pri;
0378                 PCI_CFG_W32(pcidev, PCIR_PRIBUS_1, tmp);
0379 
0380                 /* Scan Secondary Bus */
0381                 pci_find_devs(bridge);
0382 
0383                 /* sord might have been updated */
0384                 PCI_CFG_W8(pcidev, 0x1a, bridge->sord);
0385                 bus->sord = bridge->sord;
0386 
0387                 DBG("PCI-PCI BRIDGE: Primary %x, Secondary %x, "
0388                     "Subordinate %x\n",
0389                     bridge->pri, bridge->num, bridge->sord);
0390             } else {
0391                 /* Disable Cardbus CIS Pointer */
0392                 PCI_CFG_W32(pcidev, PCIR_CIS, 0);
0393 
0394                 /* Devices have subsytem device and vendor ID */
0395                 PCI_CFG_R16(pcidev, PCIR_SUBVEND_0,
0396                             &dev->subvendor);
0397                 PCI_CFG_R16(pcidev, PCIR_SUBDEV_0,
0398                             &dev->subdevice);
0399             }
0400 
0401             /* Stop if not a multi-function device */
0402             if (func == 0) {
0403                 pci_cfg_r8(pcidev, PCIR_HDRTYPE, &header);
0404                 if ((header & PCIM_MFDEV) == 0)
0405                     break;
0406             }
0407         }
0408     }
0409 }
0410 
0411 static void pci_find_bar(struct pci_dev *dev, int bar)
0412 {
0413     uint32_t size, disable, mask;
0414     struct pci_res *res = &dev->resources[bar];
0415     pci_dev_t pcidev = dev->busdevfun;
0416     int ofs;
0417 #ifdef DEBUG
0418     char *str;
0419 #define DBG_SET_STR(str, val) str = (val)
0420 #else
0421 #define DBG_SET_STR(str, val)
0422 #endif
0423 
0424     DBG("Bus: %x, Slot: %x, function: %x, bar%d\n",
0425         PCI_DEV_EXPAND(pcidev), bar);
0426 
0427     res->bar = bar;
0428     if (bar == DEV_RES_ROM) {
0429         if (dev->flags & PCI_DEV_BRIDGE)
0430             ofs = PCIR_BIOS_1;
0431         else
0432             ofs = PCIR_BIOS;
0433         disable = 0; /* ROM BARs have a unique enable bit per BAR */
0434     } else {
0435         ofs = PCIR_BAR(0) + (bar << 2);
0436         disable = pci_invalid_address;
0437     }
0438 
0439     PCI_CFG_W32(pcidev, ofs, 0xffffffff);
0440     PCI_CFG_R32(pcidev, ofs, &size);
0441     PCI_CFG_W32(pcidev, ofs, disable);
0442 
0443     if (size == 0 || size == 0xffffffff)
0444         return;
0445     if (bar == DEV_RES_ROM) {
0446         mask = PCIM_BIOS_ADDR_MASK;
0447         DBG_SET_STR(str, "ROM");
0448         if (dev->bus->flags & PCI_BUS_MEM)
0449             res->flags = PCI_RES_MEM;
0450         else
0451             res->flags = PCI_RES_MEMIO;
0452     } else if (((size & 0x1) == 0) && (size & 0x6)) {
0453         /* unsupported Memory type */
0454         PCI_CFG_W32(pcidev, ofs, 0);
0455         return;
0456     } else {
0457         mask = ~0xf;
0458         if (size & 0x1) {
0459             /* I/O */
0460             mask = ~0x3;
0461             res->flags = PCI_RES_IO;
0462             DBG_SET_STR(str, "I/O");
0463             if (size & 0xffff0000)
0464                 res->flags |= PCI_RES_IO32;
0465             /* Limit size of I/O space to 256 byte */
0466             size |= 0xffffff00;
0467             if ((dev->bus->flags & PCI_BUS_IO) == 0) {
0468                 res->flags |= PCI_RES_FAIL;
0469                 dev->flags |= PCI_DEV_RES_FAIL;
0470             }
0471         } else {
0472             /* Memory. We convert Prefetchable Memory BARs to Memory
0473              * BARs in case the Bridge does not support prefetchable
0474              * memory.
0475              */
0476             if ((size & 0x8) && (dev->bus->flags & PCI_BUS_MEM)) {
0477                 /* Prefetchable and Bus supports it */
0478                 res->flags = PCI_RES_MEM;
0479                 DBG_SET_STR(str, "MEM");
0480             } else {
0481                 res->flags = PCI_RES_MEMIO;
0482                 DBG_SET_STR(str, "MEMIO");
0483             }
0484         }
0485     }
0486     size &= mask;
0487     res->size = ~size + 1;
0488     res->boundary = ~size + 1;
0489 
0490     DBG("Bus: %x, Slot: %x, function: %x, %s bar%d size: %x\n",
0491         PCI_DEV_EXPAND(pcidev), str, bar, res->size);
0492 }
0493 
0494 static int pci_find_res_dev(struct pci_dev *dev, void *unused)
0495 {
0496     struct pci_bus *bridge;
0497     uint32_t tmp;
0498     uint16_t tmp16;
0499     pci_dev_t pcidev = dev->busdevfun;
0500     int i, maxbars;
0501 
0502     if (dev->flags & PCI_DEV_BRIDGE) {
0503         /* PCI-PCI Bridge */
0504         bridge = (struct pci_bus *)dev;
0505 
0506         /* Only 2 Bridge BARs */
0507         maxbars = 2;
0508 
0509         /* Probe Bridge Spaces (MEMIO space always implemented), the
0510          * probe disables all space-decoding at the same time
0511          */
0512         PCI_CFG_W32(pcidev, 0x30, 0);
0513         PCI_CFG_W16(pcidev, 0x1c, 0x00f0);
0514         PCI_CFG_R16(pcidev, 0x1c, &tmp16);
0515         if (tmp16 != 0) {
0516             bridge->flags |= PCI_BUS_IO;
0517             if (tmp16 & 0x1)
0518                 bridge->flags |= PCI_BUS_IO32;
0519         }
0520 
0521         PCI_CFG_W32(pcidev, 0x24, 0x0000ffff);
0522         PCI_CFG_R32(pcidev, 0x24, &tmp);
0523         if (tmp != 0)
0524             bridge->flags |= PCI_BUS_MEM;
0525 
0526         PCI_CFG_W32(pcidev, 0x20, 0x0000ffff);
0527         bridge->flags |= PCI_BUS_MEMIO;
0528     } else {
0529         /* Normal PCI Device as max 6 BARs */
0530         maxbars = 6;
0531     }
0532 
0533     /* Probe BARs */
0534     for (i = 0; i < maxbars; i++)
0535         pci_find_bar(dev, i);
0536     pci_find_bar(dev, DEV_RES_ROM);
0537 
0538     return 0;
0539 }
0540 
0541 static int pci_add_res_dev(struct pci_dev *dev, void *arg);
0542 
0543 static void pci_add_res_bus(struct pci_bus *bus, int type)
0544 {
0545     int tindex = type - 1;
0546 
0547     /* Clear old resources */
0548     bus->busres[tindex] = NULL;
0549 
0550     /* Add resources of devices behind bridge if bridge supports
0551      * resource type. If MEM space not supported by bridge, they are
0552      * converted to MEMIO in the process.
0553      */
0554     if (!((type == PCI_BUS_IO) && ((bus->flags & PCI_BUS_IO) == 0))) {
0555         pci_for_each_child(bus, pci_add_res_dev, (void *)type, 0);
0556 
0557         /* Reorder Bus resources to fit more optimally (avoid dead
0558          * PCI space). Currently they are sorted by boundary and size.
0559          *
0560          * This is especially important when multiple buses (bridges)
0561          * are present.
0562          */
0563         pci_res_reorder(bus->busres[tindex]);
0564     }
0565 }
0566 
0567 static int pci_add_res_dev(struct pci_dev *dev, void *arg)
0568 {
0569     int tindex, type = (int)arg;
0570     struct pci_bus *bridge;
0571     struct pci_res *res, *first_busres;
0572     int i;
0573     uint32_t bbound;
0574 
0575     /* Type index in Bus resource */
0576     tindex = type - 1;
0577 
0578     if (dev->flags & PCI_DEV_BRIDGE) {
0579         /* PCI-PCI Bridge. Add all sub-bus resources first */
0580         bridge = (struct pci_bus *)dev;
0581 
0582         /* Add all child device's resources to this type */
0583         pci_add_res_bus(bridge, type);
0584 
0585         /* Propagate the resources from child bus to BAR on
0586          * this bus, by adding a "fake" BAR per type.
0587          */
0588         res = &bridge->dev.resources[BUS_RES_START + tindex];
0589         res->bar = BUS_RES_START + tindex;
0590         res->start = 0;
0591         res->end = 0;
0592         res->flags = 0; /* mark BAR resource not available */
0593         first_busres = bridge->busres[tindex];
0594         if (first_busres) {
0595             res->flags = type;
0596             res->size = pci_res_size(first_busres);
0597             res->boundary = first_busres->boundary;
0598             if (type == PCI_RES_IO) {
0599                 bbound = 0x1000; /* Bridge I/O min 4KB */
0600             } else {
0601                 bbound = 0x100000; /* Bridge MEM min 1MB */
0602 
0603                 /* Convert MEM to MEMIO if not supported by
0604                  * this bridge
0605                  */
0606                 if ((bridge->flags & PCI_BUS_MEM) == 0)
0607                     res->flags = PCI_RES_MEMIO;
0608             }
0609             /* Fulfil minimum bridge boundary */
0610             if (res->boundary < bbound)
0611                 res->boundary = bbound;
0612             /* Make sure that size is atleast bridge boundary */
0613             if (res->size > bbound && (res->size & (bbound-1)))
0614                 res->size = (res->size | (bbound-1)) + 1;
0615         }
0616     }
0617 
0618     /* Normal PCI Device as max 6 BARs and a ROM Bar.
0619      * Insert BARs into the sorted resource list.
0620      */
0621     for (i = 0; i < DEV_RES_CNT; i++) {
0622         res = &dev->resources[i];
0623         if ((res->flags & PCI_RES_TYPE_MASK) != type)
0624             continue;
0625         pci_res_insert(&dev->bus->busres[tindex], res);
0626     }
0627 
0628     return 0;
0629 }
0630 
0631 /* Function assumes that base is properly aligned to the requirement of the
0632  * largest BAR in the system.
0633  */
0634 static uint32_t pci_alloc_res(struct pci_bus *bus, int type,
0635                 uint32_t start, uint32_t end)
0636 {
0637     struct pci_dev *dev;
0638     struct pci_res *res, **prev_next;
0639     unsigned long starttmp;
0640     struct pci_bus *bridge;
0641     int removed, sec_type;
0642 
0643     /* The resources are sorted on their size (size and alignment is the
0644      * same)
0645      */
0646     prev_next = &bus->busres[type - 1];
0647     while ((res = *prev_next) != NULL) {
0648 
0649         dev = RES2DEV(res);
0650         removed = 0;
0651 
0652         /* Align start to this reource's need, only needed after
0653          * a bridge resource has been allocated.
0654          */
0655         starttmp = (start + (res->boundary-1)) & ~(res->boundary-1);
0656 
0657         if ((starttmp + res->size - 1) > end) {
0658             /* Not enough memory available for this resource */
0659             printk("PCI[%x:%x:%x]: DEV BAR%d (%d): no resource "
0660                    "assigned\n",
0661                    PCI_DEV_EXPAND(dev->busdevfun),
0662                    res->bar, res->flags & PCI_RES_TYPE_MASK);
0663             res->start = res->end = 0;
0664 
0665             /* If this resources is a bridge window to the
0666              * secondary bus, the secondary resources are not
0667              * changed which has the following effect:
0668              *  I/O    :  Will never be assigned
0669              *  MEMIO  :  Will never be assigned
0670              *  MEM    :  Will stay marked as MEM, but bridge window
0671              *            is changed into MEMIO, when the window is
0672              *            assigned a MEMIO address the secondary
0673              *            resources will also be assigned.
0674              */
0675 
0676             if (type == PCI_RES_MEM) {
0677                 /* Try prefetchable as non-prefetchable mem */
0678                 res->flags &= ~PCI_RES_MEM_PREFETCH;
0679                 /* Remove resource from MEM list, ideally we
0680                  * should regenerate this list in order to fit
0681                  * the comming BARs more optimially...
0682                  */
0683                 *prev_next = res->next;
0684                 /* We should not update prev_next here since
0685                  * we just removed the resource from the list
0686                  */
0687                 removed = 1;
0688             } else {
0689                 res->flags |= PCI_RES_FAIL;
0690                 dev->flags |= PCI_DEV_RES_FAIL;
0691             }
0692         } else {
0693             start = starttmp;
0694 
0695             res->start = start;
0696             res->end = start + res->size;
0697 
0698             /* "Virtual BAR" on a bridge? A bridge resource need all
0699              * its child devices resources allocated
0700              */
0701             if ((res->bar != DEV_RES_ROM) &&
0702                 (dev->flags & PCI_DEV_BRIDGE) &&
0703                 (res->bar >= BUS_RES_START)) {
0704                 bridge = (struct pci_bus *)dev;
0705                 /* If MEM bar was changed into a MEMIO the
0706                  * secondary MEM resources are still set to MEM,
0707                  */
0708                 if (type == PCI_BUS_MEMIO &&
0709                     res->bar == BRIDGE_RES_MEM)
0710                     sec_type = PCI_RES_MEM;
0711                 else
0712                     sec_type = type;
0713 
0714                 pci_alloc_res(bridge, sec_type, res->start,
0715                         res->end);
0716             }
0717 
0718             start += res->size;
0719         }
0720         if (removed == 0)
0721             prev_next = &res->next;
0722     }
0723 
0724     return start;
0725 }
0726 
0727 static void pci_set_bar(struct pci_dev *dev, int residx)
0728 {
0729     uint32_t tmp;
0730     uint16_t tmp16;
0731     pci_dev_t pcidev;
0732     struct pci_res *res;
0733     int is_bridge, ofs;
0734 
0735     res = &dev->resources[residx];
0736     pcidev = dev->busdevfun;
0737 
0738     if ((res->flags == 0) || (res->flags & PCI_RES_FAIL))
0739         return;
0740 
0741     is_bridge = dev->flags & PCI_DEV_BRIDGE;
0742 
0743     if (res->bar == DEV_RES_ROM) {
0744         /* ROM: 32-bit prefetchable memory BAR */
0745         if (is_bridge)
0746             ofs = PCIR_BIOS_1;
0747         else
0748             ofs = PCIR_BIOS;
0749         PCI_CFG_W32(pcidev, ofs, res->start | PCIM_BIOS_ENABLE);
0750         DBG("PCI[%x:%x:%x]: ROM BAR: 0x%x-0x%x\n",
0751             PCI_DEV_EXPAND(pcidev), res->start, res->end);
0752     } else if (is_bridge && (res->bar == BRIDGE_RES_IO)) {
0753         /* PCI Bridge I/O BAR */
0754         DBG("PCI[%x:%x:%x]: BAR 1C: 0x%x-0x%x\n",
0755             PCI_DEV_EXPAND(pcidev), res->start, res->end);
0756 
0757         /* Limit and Base */
0758         tmp16 = ((res->end-1) & 0x0000f000) |
0759             ((res->start & 0x0000f000) >> 8);
0760         tmp = ((res->end-1) & 0xffff0000) | (res->start >> 16);
0761 
0762         DBG("PCI[%x:%x:%x]: BRIDGE BAR 0x%x: 0x%08x [0x30: 0x%x]\n",
0763             PCI_DEV_EXPAND(pcidev), 0x1C, tmp, tmp2);
0764         PCI_CFG_W16(pcidev, 0x1C, tmp16);
0765         PCI_CFG_W32(pcidev, 0x30, tmp);
0766     } else if (is_bridge && (res->bar >= BRIDGE_RES_MEMIO)) {
0767         /* PCI Bridge MEM and MEMIO Space */
0768 
0769         /* Limit and Base */
0770         tmp = ((res->end-1) & 0xfff00000) | (res->start >> 16);
0771 
0772         DBG("PCI[%x:%x:%x]: BRIDGE BAR 0x%x: 0x%08x\n",
0773             PCI_DEV_EXPAND(pcidev),
0774             0x20 + (res->bar-BRIDGE_RES_MEMIO)*4, tmp);
0775         PCI_CFG_W32(pcidev, 0x20+(res->bar-BRIDGE_RES_MEMIO)*4, tmp);
0776     } else {
0777         /* PCI Device */
0778         DBG("PCI[%x:%x:%x]: DEV BAR%d: 0x%08x\n",
0779             PCI_DEV_EXPAND(pcidev), res->bar, res->start);
0780         ofs = PCIR_BAR(0) + res->bar*4;
0781         PCI_CFG_W32(pcidev, ofs, res->start);
0782     }
0783 
0784     /* Enable Memory or I/O responses */
0785     if ((res->flags & PCI_RES_TYPE_MASK) == PCI_RES_IO)
0786         pci_io_enable(pcidev);
0787     else
0788         pci_mem_enable(pcidev);
0789 
0790     /* Enable Master if bridge */
0791     if (is_bridge)
0792         pci_master_enable(pcidev);
0793 }
0794 
0795 static int pci_set_res_dev(struct pci_dev *dev, void *unused)
0796 {
0797     int i, maxbars;
0798 
0799     if (dev->flags & PCI_DEV_BRIDGE)
0800         maxbars = 2 + 3; /* 2 BARs + 3 Bridge-Windows "Virtual BARs" */
0801     else
0802         maxbars = 6; /* Normal PCI Device as max 6 BARs. */
0803 
0804     /* Set BAR resources with previous allocated values */
0805     for (i = 0; i < maxbars; i++)
0806         pci_set_bar(dev, i);
0807     pci_set_bar(dev, DEV_RES_ROM);
0808 
0809     return 0;
0810 }
0811 
0812 /* Route IRQ through PCI-PCI Bridges */
0813 static int pci_route_irq(pci_dev_t dev, int irq_pin)
0814 {
0815     int slot_grp;
0816 
0817     if (PCI_DEV_BUS(dev) == 0)
0818         return irq_pin;
0819 
0820     slot_grp = PCI_DEV_SLOT(dev) & 0x3;
0821 
0822     return (((irq_pin - 1) + slot_grp) & 0x3) + 1;
0823 }
0824 
0825 /* Put assigned system IRQ into PCI interrupt line information field.
0826  * This is to make it possible for drivers to read system IRQ / Vector from
0827  * configuration space later on.
0828  *
0829  * 1. Get Interrupt PIN
0830  * 2. Route PIN to host bridge
0831  * 3. Get System interrupt number assignment for PIN
0832  * 4. Set Interrupt LINE
0833  */
0834 static int pci_set_irq_dev(struct pci_dev *dev, void *cfg)
0835 {
0836     struct pci_auto_setup *autocfg = cfg;
0837     uint8_t irq_pin, irq_line, *psysirq;
0838     pci_dev_t pcidev;
0839 
0840     psysirq = &dev->sysirq;
0841     pcidev = dev->busdevfun;
0842     PCI_CFG_R8(pcidev, PCIR_INTPIN, &irq_pin);
0843 
0844     /* perform IRQ routing until we reach host bridge */
0845     while (dev->bus && irq_pin != 0) {
0846         irq_pin = autocfg->irq_route(dev->busdevfun, irq_pin);
0847         dev = &dev->bus->dev;
0848     }
0849 
0850     /* Get IRQ from PIN on PCI bus0 */
0851     if (irq_pin != 0 && autocfg->irq_map)
0852         irq_line = autocfg->irq_map(dev->busdevfun, irq_pin);
0853     else
0854         irq_line = 0;
0855 
0856     *psysirq = irq_line;
0857 
0858     /* Set System Interrupt/Vector for device. 0 means no-IRQ */
0859     PCI_CFG_W8(pcidev, PCIR_INTLINE, irq_line);
0860 
0861     return 0;
0862 }
0863 
0864 /* This routine assumes that PCI access library has been successfully
0865  * initialized. All information about the PCI bus needed is found in
0866  * the pci_auto_cfg structure passed on by pci_config_register().
0867  *
0868  * The PCI buses are enumerated as bridges are found, PCI devices are
0869  * setup with BARs and IRQs, etc.
0870  */
0871 int pci_config_auto(void)
0872 {
0873     uint32_t end;
0874     uint32_t startmemio, startmem, startio;
0875     struct pci_auto_setup *autocfg = &pci_auto_cfg;
0876 #ifdef DEBUG
0877     uint32_t endmemio, endmem, endio;
0878     uint32_t start;
0879 #endif
0880 
0881     if (pci_config_auto_initialized == 0)
0882         return -1; /* no config given to library */
0883 
0884 #ifdef DEBUG
0885     DBG("\n--- PCI MEMORY AVAILABLE ---\n");
0886     if (autocfg->mem_size) {
0887         start = autocfg->mem_start;
0888         end = autocfg->mem_start + autocfg->mem_size - 1;
0889         DBG(" MEM AVAIL [0x%08x-0x%08x]\n", start, end);
0890     } else {
0891         /* One big memory space */
0892         DBG(" MEM share the space with MEMIO\n");
0893     }
0894     /* no-prefetchable memory space need separate memory space.
0895      * For example PCI controller maps this region non-cachable.
0896      */
0897     start = autocfg->memio_start;
0898     end = autocfg->memio_start + autocfg->memio_size - 1;
0899     DBG(" MEMIO AVAIL [0x%08x-0x%08x]\n", start, end);
0900     if (autocfg->io_size) {
0901         start = autocfg->io_start;
0902         end = autocfg->io_start + autocfg->io_size - 1;
0903         DBG(" I/O AVAIL [0x%08x-0x%08x]\n", start, end);
0904     } else {
0905         DBG(" I/O Space not available\n");
0906     }
0907 #endif
0908 
0909     /* Init Host-Bridge */
0910     memset(&pci_hb, 0, sizeof(pci_hb));
0911     pci_hb.dev.flags = PCI_DEV_BRIDGE;
0912     if (autocfg->memio_size <= 0)
0913         return -1;
0914     pci_hb.flags = PCI_BUS_MEMIO;
0915     if (autocfg->mem_size)
0916         pci_hb.flags |= PCI_BUS_MEM;
0917     if (autocfg->io_size)
0918         pci_hb.flags |= PCI_BUS_IO;
0919 
0920     /* Find all PCI devices/functions on all buses. The buses will be
0921      * enumrated (assigned a unique PCI Bus ID 0..255).
0922      */
0923     DBG("\n--- PCI SCANNING ---\n");
0924     pci_find_devs(&pci_hb);
0925     pci_bus_cnt = pci_hb.sord + 1;
0926     if (pci_hb.devs == NULL)
0927         return 0;
0928 
0929     pci_system_type = PCI_SYSTEM_HOST;
0930 
0931     /* Find all resources (MEM/MEMIO/IO BARs) of all devices/functions
0932      * on all buses.
0933      *
0934      * Device resources behind bridges which does not support prefetchable
0935      * memory are already marked as non-prefetchable memory.
0936      * Devices which as I/O resources behind a bridge that do not support
0937      * I/O space are marked DISABLED.
0938      *
0939      * All BARs and Bridge Spaces are disabled after this. Only the ones
0940      * that are allocated an address are initilized later on.
0941      */
0942     DBG("\n\n--- PCI RESOURCES ---\n");
0943     pci_for_each_dev(pci_find_res_dev, 0);
0944 
0945     /* Add all device's resources to bus and sort them to fit in the PCI
0946      * Window. The device resources are propagated upwards through bridges
0947      * by adding a "virtual" BAR (boundary != BAR size).
0948      *
0949      * We wait with MEMIO (non-prefetchable memory) resources to after MEM
0950      * resources have been allocated, so that MEM resources can be changed
0951      * into MEMIO resources if not enough space.
0952      */
0953     pci_add_res_bus(&pci_hb, PCI_RES_IO);
0954     pci_add_res_bus(&pci_hb, PCI_RES_MEM);
0955 
0956     /* Start assigning found resource according to the sorted order. */
0957 
0958     /* Allocate resources to I/O areas */
0959     if (pci_hb.busres[BUS_RES_IO]) {
0960         startio = autocfg->io_start;
0961         end = startio + autocfg->io_size;
0962 #ifdef DEBUG
0963         endio =
0964 #endif
0965             pci_alloc_res(&pci_hb, PCI_RES_IO, startio, end);
0966     }
0967 
0968     /* Allocate resources to prefetchable memory */
0969     if (pci_hb.busres[BUS_RES_MEM]) {
0970         startmem = autocfg->mem_start;
0971         end = startmem + autocfg->mem_size;
0972 #ifdef DEBUG
0973         endmem =
0974 #endif
0975             pci_alloc_res(&pci_hb, PCI_RES_MEM, startmem, end);
0976     }
0977 
0978     /* Add non-prefetchable memory resources and not fitting prefetchable
0979      * memory resources.
0980      *
0981      * Some prefetchable memory resources may not have fitted into PCI
0982      * window. Prefetchable memory can be mapped into non-prefetchable
0983      * memory window. The failing BARs have been marked as MEMIO instead.
0984      */
0985     pci_add_res_bus(&pci_hb, PCI_RES_MEMIO);
0986 
0987     /* Allocate resources to non-prefetchable memory */
0988     if (pci_hb.busres[BUS_RES_MEMIO]) {
0989         startmemio = autocfg->memio_start;
0990         end = startmemio + autocfg->memio_size;
0991 #ifdef DEBUG
0992         endmemio =
0993 #endif
0994             pci_alloc_res(&pci_hb, PCI_RES_MEMIO, startmemio, end);
0995     }
0996 
0997     DBG("\n--- PCI ALLOCATED SPACE RANGES ---\n");
0998     DBG(" MEM NON-PREFETCHABLE: [0x%08x-0x%08x]\n", startmemio, endmemio);
0999     DBG(" MEM PREFETCHABLE:     [0x%08x-0x%08x]\n", startmem, endmem);
1000     DBG(" I/O:                  [0x%08x-0x%08x]\n", startio, endio);
1001 
1002     /* Set all allocated BARs and Bridge Windows */
1003     pci_for_each_dev(pci_set_res_dev, NULL);
1004 
1005     /* Initialize IRQs of all devices. According to the PCI-PCI bridge
1006      * specification the IRQs are routed differently depending on slot
1007      * number. Drivers can override the default routing if a motherboard
1008      * requires it.
1009      */
1010     if ((autocfg->options & CFGOPT_NOSETUP_IRQ) == 0) {
1011         if (autocfg->irq_route == NULL) /* use standard irq routing */
1012             autocfg->irq_route = pci_route_irq;
1013         pci_for_each_dev(pci_set_irq_dev, autocfg);
1014     }
1015 
1016     DBG("PCI resource allocation done\n");
1017 
1018     return 0;
1019 }
1020 
1021 void pci_config_auto_register(void *config)
1022 {
1023     pci_config_auto_initialized = 1;
1024     memcpy(&pci_auto_cfg, config, sizeof(struct pci_auto_setup));
1025 }