File indexing completed on 2025-05-11 08:24:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <rtems.h>
0031 #include <stdlib.h>
0032 #include <rtems/bspIo.h>
0033 #include <pci/cfg.h>
0034 #include <pci/access.h>
0035
0036 #include "pci_internal.h"
0037
0038
0039
0040
0041
0042 #define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
0043 #define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
0044 #define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
0045 #define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
0046 #define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
0047 #define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
0048
0049 #ifdef DEBUG
0050 #define DBG(args...) printk(args)
0051 #else
0052 #define DBG(args...)
0053 #endif
0054
0055
0056 extern struct pci_bus pci_hb;
0057
0058 static struct pci_dev *pci_dev_create(int isbus)
0059 {
0060 void *ptr;
0061 int size;
0062
0063 if (isbus)
0064 size = sizeof(struct pci_bus);
0065 else
0066 size = sizeof(struct pci_dev);
0067
0068 ptr = calloc(1, size);
0069 if (!ptr)
0070 rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
0071 return ptr;
0072 }
0073
0074
0075 static int pci_read_addressable(struct pci_dev *dev, struct pci_res *res)
0076 {
0077 struct pci_bus *bus = dev->bus;
0078 int type = res->flags & PCI_RES_TYPE_MASK;
0079 struct pci_res *range0, *range1;
0080
0081 if (type == PCI_BUS_IO && (bus->flags & PCI_BUS_IO) == 0)
0082 return 0;
0083
0084
0085 if (bus->pri == 0)
0086 return 1;
0087
0088 range1 = NULL;
0089 switch (type) {
0090 case PCI_RES_IO:
0091 range0 = &bus->dev.resources[BRIDGE_RES_IO];
0092 break;
0093 case PCI_RES_MEM:
0094 range1 = &bus->dev.resources[BRIDGE_RES_MEM];
0095
0096 default:
0097 case PCI_RES_MEMIO:
0098 range0 = &bus->dev.resources[BRIDGE_RES_MEMIO];
0099 break;
0100 }
0101 if ((res->start >= range0->start) && (res->end <= range0->end)) {
0102 return pci_read_addressable(&bus->dev, range0);
0103 } else if (range1 && (res->start >= range1->start) &&
0104 (res->end <= range1->end)) {
0105 return pci_read_addressable(&bus->dev, range1);
0106 }
0107
0108 return 0;
0109 }
0110
0111 static void pci_read_bar(struct pci_dev *dev, int bar)
0112 {
0113 uint32_t orig, size, mask;
0114 struct pci_res *res = &dev->resources[bar];
0115 pci_dev_t pcidev = dev->busdevfun;
0116 int ofs;
0117 #ifdef DEBUG
0118 char *str;
0119 #define DBG_SET_STR(str, val) str = (val)
0120 #else
0121 #define DBG_SET_STR(str, val)
0122 #endif
0123
0124 DBG("Bus: %x, Slot: %x, function: %x, bar%d\n",
0125 PCI_DEV_EXPAND(pcidev), bar);
0126
0127 res->bar = bar;
0128 if (bar == DEV_RES_ROM) {
0129 if (dev->flags & PCI_DEV_BRIDGE)
0130 ofs = PCIR_BIOS_1;
0131 else
0132 ofs = PCIR_BIOS;
0133 } else {
0134 ofs = PCIR_BAR(0) + (bar << 2);
0135 }
0136
0137 PCI_CFG_R32(pcidev, ofs, &orig);
0138 PCI_CFG_W32(pcidev, ofs, 0xffffffff);
0139 PCI_CFG_R32(pcidev, ofs, &size);
0140 PCI_CFG_W32(pcidev, ofs, orig);
0141
0142 if (size == 0 || size == 0xffffffff)
0143 return;
0144 if (bar == DEV_RES_ROM) {
0145 mask = PCIM_BIOS_ADDR_MASK;
0146 DBG_SET_STR(str, "ROM");
0147 if (dev->bus->flags & PCI_BUS_MEM)
0148 res->flags = PCI_RES_MEM;
0149 else
0150 res->flags = PCI_RES_MEMIO;
0151 } else if (((size & 0x1) == 0) && (size & 0x6)) {
0152
0153 return;
0154 } else {
0155 mask = ~0xf;
0156 if (size & 0x1) {
0157
0158 mask = ~0x3;
0159 res->flags = PCI_RES_IO;
0160 DBG_SET_STR(str, "I/O");
0161 if (size & 0xffff0000)
0162 res->flags |= PCI_RES_IO32;
0163
0164 size |= 0xffffff00;
0165 if ((dev->bus->flags & PCI_BUS_IO) == 0) {
0166 res->flags |= PCI_RES_FAIL;
0167 dev->flags |= PCI_DEV_RES_FAIL;
0168 }
0169 } else {
0170
0171 if (size & 0x8) {
0172
0173 res->flags = PCI_RES_MEM;
0174 DBG_SET_STR(str, "MEM");
0175 } else {
0176 res->flags = PCI_RES_MEMIO;
0177 DBG_SET_STR(str, "MEMIO");
0178 }
0179 }
0180 }
0181 res->start = orig & mask;
0182 size &= mask;
0183 res->size = ~size + 1;
0184 res->boundary = res->size;
0185 res->end = res->start + res->size;
0186
0187 DBG("Bus: %x, Slot: %x, function: %x, %s bar%d size: %x\n",
0188 PCI_DEV_EXPAND(pcidev), str, bar, res->size);
0189
0190
0191 if (pci_read_addressable(dev, res) == 0) {
0192
0193 res->flags |= PCI_RES_FAIL;
0194 dev->flags |= PCI_DEV_RES_FAIL;
0195 }
0196 }
0197
0198 static void pci_read_devs(struct pci_bus *bus)
0199 {
0200 uint32_t id, tmp;
0201 uint16_t tmp16;
0202 uint8_t header;
0203 int slot, func, fail, i, maxbars, max_sord;
0204 struct pci_dev *dev, **listptr;
0205 struct pci_bus *bridge;
0206 pci_dev_t pcidev;
0207 struct pci_res *res;
0208
0209 DBG("Scanning bus %d\n", bus->num);
0210
0211 max_sord = bus->num;
0212 listptr = &bus->devs;
0213 for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
0214
0215
0216 pcidev = PCI_DEV(bus->num, slot, 0);
0217
0218 for (func = 0; func <= PCI_FUNCMAX; func++, pcidev++) {
0219
0220 fail = PCI_CFG_R32(pcidev, PCIR_VENDOR, &id);
0221 if (fail || id == 0xffffffff || id == 0) {
0222
0223
0224
0225 if (func == 0)
0226 break;
0227 else
0228 continue;
0229 }
0230
0231 DBG("Found PCIDEV 0x%x at (bus %x, slot %x, func %x)\n",
0232 id, bus, slot, func);
0233
0234 PCI_CFG_R32(pcidev, PCIR_REVID, &tmp);
0235 tmp >>= 16;
0236 dev = pci_dev_create(tmp == PCID_PCI2PCI_BRIDGE);
0237 *listptr = dev;
0238 listptr = &dev->next;
0239
0240 dev->busdevfun = pcidev;
0241 dev->bus = bus;
0242 PCI_CFG_R16(pcidev, PCIR_VENDOR, &dev->vendor);
0243 PCI_CFG_R16(pcidev, PCIR_DEVICE, &dev->device);
0244 PCI_CFG_R32(pcidev, PCIR_REVID, &dev->classrev);
0245
0246 if (tmp == PCID_PCI2PCI_BRIDGE) {
0247 DBG("Found PCI-PCI Bridge 0x%x at "
0248 "(bus %x, slot %x, func %x)\n",
0249 id, bus, slot, func);
0250 dev->flags = PCI_DEV_BRIDGE;
0251 bridge = (struct pci_bus *)dev;
0252
0253 PCI_CFG_R32(pcidev, PCIR_PRIBUS_1, &tmp);
0254 bridge->pri = tmp & 0xff;
0255 bridge->num = (tmp >> 8) & 0xff;
0256 bridge->sord = (tmp >> 16) & 0xff;
0257 if (bridge->sord > max_sord)
0258 max_sord = bridge->sord;
0259
0260 DBG(" Primary %x, Secondary %x, "
0261 "Subordinate %x\n",
0262 bridge->pri, bridge->num, bridge->sord);
0263
0264
0265
0266
0267 bridge->flags = PCI_BUS_MEMIO;
0268 res = &bridge->dev.resources[BRIDGE_RES_MEMIO];
0269 res->flags = PCI_RES_MEMIO;
0270 res->bar = BRIDGE_RES_MEMIO;
0271 PCI_CFG_R32(pcidev, 0x20, &tmp);
0272 res->start = (tmp & 0xfff0) << 16;
0273 res->end = 1 + ((tmp & 0xfff00000) | 0xfffff);
0274 if (res->end <= res->start) {
0275
0276 res->end = res->start = 0;
0277 }
0278 res->size = res->end - res->start;
0279
0280
0281 res = &bridge->dev.resources[BRIDGE_RES_IO];
0282 res->bar = BRIDGE_RES_IO;
0283 PCI_CFG_R32(pcidev, 0x30, &tmp);
0284 PCI_CFG_R16(pcidev, 0x1c, &tmp16);
0285 if (tmp != 0 || tmp16 != 0) {
0286 bridge->flags |= PCI_BUS_IO;
0287 res->flags = PCI_RES_IO;
0288 if (tmp16 & 0x1) {
0289 bridge->flags |= PCI_BUS_IO32;
0290 res->flags |= PCI_RES_IO32;
0291 }
0292
0293 res->start = (tmp & 0xffff) << 16 |
0294 (tmp16 & 0xf0) << 8;
0295 res->end = 1 + ((tmp & 0xffff0000) |
0296 (tmp16 & 0xf000) |
0297 0xfff);
0298 if (res->end <= res->start) {
0299
0300 res->end = res->start = 0;
0301 }
0302 res->size = res->end - res->start;
0303 }
0304
0305
0306 res = &bridge->dev.resources[BRIDGE_RES_MEM];
0307 res->bar = BRIDGE_RES_MEM;
0308 PCI_CFG_R32(pcidev, 0x24, &tmp);
0309 if (tmp != 0) {
0310 bridge->flags |= PCI_BUS_MEM;
0311 res->flags = PCI_RES_MEM;
0312 res->start = (tmp & 0xfff0) << 16;
0313 res->end = 1 + ((tmp & 0xfff00000) |
0314 0xfffff);
0315 if (res->end <= res->start) {
0316
0317 res->end = res->start = 0;
0318 }
0319 res->size = res->end - res->start;
0320 }
0321
0322
0323 pci_read_devs(bridge);
0324
0325
0326 maxbars = 2;
0327 } else {
0328
0329 PCI_CFG_R16(pcidev, PCIR_SUBVEND_0,
0330 &dev->subvendor);
0331 PCI_CFG_R16(pcidev, PCIR_SUBDEV_0,
0332 &dev->subdevice);
0333
0334
0335 maxbars = 6;
0336 }
0337
0338
0339 for (i = 0; i < maxbars; i++)
0340 pci_read_bar(dev, i);
0341 pci_read_bar(dev, DEV_RES_ROM);
0342
0343
0344
0345
0346 PCI_CFG_R8(pcidev, PCIR_INTLINE, &dev->sysirq);
0347
0348
0349 if (func == 0) {
0350 pci_cfg_r8(pcidev, PCIR_HDRTYPE, &header);
0351 if ((header & PCIM_MFDEV) == 0)
0352 break;
0353 }
0354 }
0355 }
0356
0357 if (bus->num == 0)
0358 bus->sord = max_sord;
0359 }
0360
0361 int pci_config_read(void)
0362 {
0363 pci_system_type = PCI_SYSTEM_HOST;
0364
0365
0366 pci_hb.flags = PCI_BUS_IO|PCI_BUS_MEMIO|PCI_BUS_MEM;
0367 pci_hb.dev.flags = PCI_DEV_BRIDGE;
0368 pci_read_devs(&pci_hb);
0369 pci_bus_cnt = pci_hb.sord + 1;
0370 if (pci_hb.devs == NULL)
0371 return 0;
0372
0373 return 0;
0374 }