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 #include <rtems.h>
0030 #include <stdlib.h>
0031 #include <rtems/bspIo.h>
0032 #include <string.h>
0033
0034
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
0044
0045 #ifdef DEBUG
0046 #define DBG(x...) printk(x)
0047 #else
0048 #define DBG(x...)
0049 #endif
0050
0051
0052
0053
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
0065 struct pci_auto_setup pci_auto_cfg;
0066
0067
0068
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
0082
0083
0084
0085
0086
0087
0088
0089 last = NULL;
0090 curr = *root;
0091
0092
0093
0094
0095
0096
0097
0098 while (curr && (curr->boundary >= boundary)) {
0099 if (curr->boundary == boundary) {
0100
0101 size_resulting_boundary = 1;
0102 while ((size & size_resulting_boundary) == 0)
0103 size_resulting_boundary =
0104 size_resulting_boundary << 1;
0105
0106
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
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
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
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
0189
0190
0191 start = root->boundary + root->size;
0192 last = root;
0193 curr = root->next;
0194 while (curr) {
0195
0196
0197 start_next = (start + (curr->boundary - 1)) &
0198 ~(curr->boundary - 1);
0199
0200
0201
0202 hole_size = start_next - start;
0203
0204
0205 hole_boundary = 1;
0206 while ((start & hole_boundary) == 0)
0207 hole_boundary = hole_boundary<<1;
0208
0209
0210 if (hole_size > 0) {
0211
0212
0213
0214
0215 last2 = curr;
0216 curr2 = curr->next;
0217 while (curr2) {
0218 if ((curr2->boundary <= hole_boundary) &&
0219 (curr2->size <= hole_size)) {
0220
0221
0222
0223
0224
0225 last2->next = curr2->next;
0226 curr2->next = curr;
0227 last->next = curr2;
0228
0229
0230 start_next = (start +
0231 (curr2->boundary - 1)) &
0232 ~(curr2->boundary - 1);
0233
0234
0235
0236
0237
0238 curr = curr2;
0239 break;
0240 }
0241 last2 = curr2;
0242 curr2 = curr2->next;
0243 }
0244 }
0245
0246
0247 start = start_next;
0248
0249 last = curr;
0250 curr = curr->next;
0251 }
0252 }
0253
0254
0255 static unsigned int pci_res_size(struct pci_res *root)
0256 {
0257 struct pci_res *curr;
0258 unsigned int size;
0259
0260
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
0273
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
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
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
0339
0340
0341 PCI_CFG_W16(pcidev, PCIR_COMMAND, 0);
0342
0343
0344 PCI_CFG_W16(pcidev, PCIR_STATUS, 0xf900);
0345
0346
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
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
0381 pci_find_devs(bridge);
0382
0383
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
0392 PCI_CFG_W32(pcidev, PCIR_CIS, 0);
0393
0394
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
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;
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
0454 PCI_CFG_W32(pcidev, ofs, 0);
0455 return;
0456 } else {
0457 mask = ~0xf;
0458 if (size & 0x1) {
0459
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
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
0473
0474
0475
0476 if ((size & 0x8) && (dev->bus->flags & PCI_BUS_MEM)) {
0477
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
0504 bridge = (struct pci_bus *)dev;
0505
0506
0507 maxbars = 2;
0508
0509
0510
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
0530 maxbars = 6;
0531 }
0532
0533
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
0548 bus->busres[tindex] = NULL;
0549
0550
0551
0552
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
0558
0559
0560
0561
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
0576 tindex = type - 1;
0577
0578 if (dev->flags & PCI_DEV_BRIDGE) {
0579
0580 bridge = (struct pci_bus *)dev;
0581
0582
0583 pci_add_res_bus(bridge, type);
0584
0585
0586
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;
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;
0600 } else {
0601 bbound = 0x100000;
0602
0603
0604
0605
0606 if ((bridge->flags & PCI_BUS_MEM) == 0)
0607 res->flags = PCI_RES_MEMIO;
0608 }
0609
0610 if (res->boundary < bbound)
0611 res->boundary = bbound;
0612
0613 if (res->size > bbound && (res->size & (bbound-1)))
0614 res->size = (res->size | (bbound-1)) + 1;
0615 }
0616 }
0617
0618
0619
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
0632
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
0644
0645
0646 prev_next = &bus->busres[type - 1];
0647 while ((res = *prev_next) != NULL) {
0648
0649 dev = RES2DEV(res);
0650 removed = 0;
0651
0652
0653
0654
0655 starttmp = (start + (res->boundary-1)) & ~(res->boundary-1);
0656
0657 if ((starttmp + res->size - 1) > end) {
0658
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
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676 if (type == PCI_RES_MEM) {
0677
0678 res->flags &= ~PCI_RES_MEM_PREFETCH;
0679
0680
0681
0682
0683 *prev_next = res->next;
0684
0685
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
0699
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
0706
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
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
0754 DBG("PCI[%x:%x:%x]: BAR 1C: 0x%x-0x%x\n",
0755 PCI_DEV_EXPAND(pcidev), res->start, res->end);
0756
0757
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
0768
0769
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
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
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
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;
0801 else
0802 maxbars = 6;
0803
0804
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
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
0826
0827
0828
0829
0830
0831
0832
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
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
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
0859 PCI_CFG_W8(pcidev, PCIR_INTLINE, irq_line);
0860
0861 return 0;
0862 }
0863
0864
0865
0866
0867
0868
0869
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;
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
0892 DBG(" MEM share the space with MEMIO\n");
0893 }
0894
0895
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
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
0921
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
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942 DBG("\n\n--- PCI RESOURCES ---\n");
0943 pci_for_each_dev(pci_find_res_dev, 0);
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953 pci_add_res_bus(&pci_hb, PCI_RES_IO);
0954 pci_add_res_bus(&pci_hb, PCI_RES_MEM);
0955
0956
0957
0958
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
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
0979
0980
0981
0982
0983
0984
0985 pci_add_res_bus(&pci_hb, PCI_RES_MEMIO);
0986
0987
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
1003 pci_for_each_dev(pci_set_res_dev, NULL);
1004
1005
1006
1007
1008
1009
1010 if ((autocfg->options & CFGOPT_NOSETUP_IRQ) == 0) {
1011 if (autocfg->irq_route == NULL)
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 }