Annotation of qemu/hw/pci_bridge.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * QEMU PCI bus manager
                      3:  *
                      4:  * Copyright (c) 2004 Fabrice Bellard
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to dea
                      8: 
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
                     22: 
                     23:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     24:  * THE SOFTWARE.
                     25:  */
                     26: /*
                     27:  * split out from pci.c
                     28:  * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
                     29:  *                    VA Linux Systems Japan K.K.
                     30:  */
                     31: 
                     32: #include "pci_bridge.h"
                     33: #include "pci_internals.h"
                     34: #include "range.h"
                     35: 
                     36: /* PCI bridge subsystem vendor ID helper functions */
                     37: #define PCI_SSVID_SIZEOF        8
                     38: #define PCI_SSVID_SVID          4
                     39: #define PCI_SSVID_SSID          6
                     40: 
                     41: int pci_bridge_ssvid_init(PCIDevice *dev, uint8_t offset,
                     42:                           uint16_t svid, uint16_t ssid)
                     43: {
                     44:     int pos;
                     45:     pos = pci_add_capability(dev, PCI_CAP_ID_SSVID, offset, PCI_SSVID_SIZEOF);
                     46:     if (pos < 0) {
                     47:         return pos;
                     48:     }
                     49: 
                     50:     pci_set_word(dev->config + pos + PCI_SSVID_SVID, svid);
                     51:     pci_set_word(dev->config + pos + PCI_SSVID_SSID, ssid);
                     52:     return pos;
                     53: }
                     54: 
                     55: /* Accessor function to get parent bridge device from pci bus. */
                     56: PCIDevice *pci_bridge_get_device(PCIBus *bus)
                     57: {
                     58:     return bus->parent_dev;
                     59: }
                     60: 
                     61: /* Accessor function to get secondary bus from pci-to-pci bridge device */
                     62: PCIBus *pci_bridge_get_sec_bus(PCIBridge *br)
                     63: {
                     64:     return &br->sec_bus;
                     65: }
                     66: 
                     67: static uint32_t pci_config_get_io_base(const PCIDevice *d,
                     68:                                        uint32_t base, uint32_t base_upper16)
                     69: {
                     70:     uint32_t val;
                     71: 
                     72:     val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8;
                     73:     if (d->config[base] & PCI_IO_RANGE_TYPE_32) {
                     74:         val |= (uint32_t)pci_get_word(d->config + base_upper16) << 16;
                     75:     }
                     76:     return val;
                     77: }
                     78: 
                     79: static pcibus_t pci_config_get_memory_base(const PCIDevice *d, uint32_t base)
                     80: {
                     81:     return ((pcibus_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK)
                     82:         << 16;
                     83: }
                     84: 
                     85: static pcibus_t pci_config_get_pref_base(const PCIDevice *d,
                     86:                                          uint32_t base, uint32_t upper)
                     87: {
                     88:     pcibus_t tmp;
                     89:     pcibus_t val;
                     90: 
                     91:     tmp = (pcibus_t)pci_get_word(d->config + base);
                     92:     val = (tmp & PCI_PREF_RANGE_MASK) << 16;
                     93:     if (tmp & PCI_PREF_RANGE_TYPE_64) {
                     94:         val |= (pcibus_t)pci_get_long(d->config + upper) << 32;
                     95:     }
                     96:     return val;
                     97: }
                     98: 
                     99: /* accessor function to get bridge filtering base address */
                    100: pcibus_t pci_bridge_get_base(const PCIDevice *bridge, uint8_t type)
                    101: {
                    102:     pcibus_t base;
                    103:     if (type & PCI_BASE_ADDRESS_SPACE_IO) {
                    104:         base = pci_config_get_io_base(bridge,
                    105:                                       PCI_IO_BASE, PCI_IO_BASE_UPPER16);
                    106:     } else {
                    107:         if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
                    108:             base = pci_config_get_pref_base(
                    109:                 bridge, PCI_PREF_MEMORY_BASE, PCI_PREF_BASE_UPPER32);
                    110:         } else {
                    111:             base = pci_config_get_memory_base(bridge, PCI_MEMORY_BASE);
                    112:         }
                    113:     }
                    114: 
                    115:     return base;
                    116: }
                    117: 
                    118: /* accessor funciton to get bridge filtering limit */
                    119: pcibus_t pci_bridge_get_limit(const PCIDevice *bridge, uint8_t type)
                    120: {
                    121:     pcibus_t limit;
                    122:     if (type & PCI_BASE_ADDRESS_SPACE_IO) {
                    123:         limit = pci_config_get_io_base(bridge,
                    124:                                       PCI_IO_LIMIT, PCI_IO_LIMIT_UPPER16);
                    125:         limit |= 0xfff;         /* PCI bridge spec 3.2.5.6. */
                    126:     } else {
                    127:         if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
                    128:             limit = pci_config_get_pref_base(
                    129:                 bridge, PCI_PREF_MEMORY_LIMIT, PCI_PREF_LIMIT_UPPER32);
                    130:         } else {
                    131:             limit = pci_config_get_memory_base(bridge, PCI_MEMORY_LIMIT);
                    132:         }
                    133:         limit |= 0xfffff;       /* PCI bridge spec 3.2.5.{1, 8}. */
                    134:     }
                    135:     return limit;
                    136: }
                    137: 
1.1.1.2 ! root      138: static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias,
        !           139:                                   uint8_t type, const char *name,
        !           140:                                   MemoryRegion *space,
        !           141:                                   MemoryRegion *parent_space,
        !           142:                                   bool enabled)
        !           143: {
        !           144:     pcibus_t base = pci_bridge_get_base(&bridge->dev, type);
        !           145:     pcibus_t limit = pci_bridge_get_limit(&bridge->dev, type);
        !           146:     /* TODO: this doesn't handle base = 0 limit = 2^64 - 1 correctly.
        !           147:      * Apparently no way to do this with existing memory APIs. */
        !           148:     pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0;
        !           149: 
        !           150:     memory_region_init_alias(alias, name, space, base, size);
        !           151:     memory_region_add_subregion_overlap(parent_space, base, alias, 1);
        !           152: }
        !           153: 
        !           154: static void pci_bridge_cleanup_alias(MemoryRegion *alias,
        !           155:                                      MemoryRegion *parent_space)
        !           156: {
        !           157:     memory_region_del_subregion(parent_space, alias);
        !           158:     memory_region_destroy(alias);
        !           159: }
        !           160: 
        !           161: static void pci_bridge_region_init(PCIBridge *br)
        !           162: {
        !           163:     PCIBus *parent = br->dev.bus;
        !           164:     uint16_t cmd = pci_get_word(br->dev.config + PCI_COMMAND);
        !           165: 
        !           166:     pci_bridge_init_alias(br, &br->alias_pref_mem,
        !           167:                           PCI_BASE_ADDRESS_MEM_PREFETCH,
        !           168:                           "pci_bridge_pref_mem",
        !           169:                           &br->address_space_mem,
        !           170:                           parent->address_space_mem,
        !           171:                           cmd & PCI_COMMAND_MEMORY);
        !           172:     pci_bridge_init_alias(br, &br->alias_mem,
        !           173:                           PCI_BASE_ADDRESS_SPACE_MEMORY,
        !           174:                           "pci_bridge_mem",
        !           175:                           &br->address_space_mem,
        !           176:                           parent->address_space_mem,
        !           177:                           cmd & PCI_COMMAND_MEMORY);
        !           178:     pci_bridge_init_alias(br, &br->alias_io,
        !           179:                           PCI_BASE_ADDRESS_SPACE_IO,
        !           180:                           "pci_bridge_io",
        !           181:                           &br->address_space_io,
        !           182:                           parent->address_space_io,
        !           183:                           cmd & PCI_COMMAND_IO);
        !           184:    /* TODO: optinal VGA and VGA palette snooping support. */
        !           185: }
        !           186: 
        !           187: static void pci_bridge_region_cleanup(PCIBridge *br)
        !           188: {
        !           189:     PCIBus *parent = br->dev.bus;
        !           190:     pci_bridge_cleanup_alias(&br->alias_io,
        !           191:                              parent->address_space_io);
        !           192:     pci_bridge_cleanup_alias(&br->alias_mem,
        !           193:                              parent->address_space_mem);
        !           194:     pci_bridge_cleanup_alias(&br->alias_pref_mem,
        !           195:                              parent->address_space_mem);
        !           196: }
        !           197: 
        !           198: static void pci_bridge_update_mappings(PCIBridge *br)
        !           199: {
        !           200:     /* Make updates atomic to: handle the case of one VCPU updating the bridge
        !           201:      * while another accesses an unaffected region. */
        !           202:     memory_region_transaction_begin();
        !           203:     pci_bridge_region_cleanup(br);
        !           204:     pci_bridge_region_init(br);
        !           205:     memory_region_transaction_commit();
        !           206: }
        !           207: 
1.1       root      208: /* default write_config function for PCI-to-PCI bridge */
                    209: void pci_bridge_write_config(PCIDevice *d,
                    210:                              uint32_t address, uint32_t val, int len)
                    211: {
                    212:     PCIBridge *s = container_of(d, PCIBridge, dev);
                    213:     uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
                    214:     uint16_t newctl;
                    215: 
                    216:     pci_default_write_config(d, address, val, len);
                    217: 
1.1.1.2 ! root      218:     if (ranges_overlap(address, len, PCI_COMMAND, 2) ||
        !           219: 
        !           220:         /* io base/limit */
1.1       root      221:         ranges_overlap(address, len, PCI_IO_BASE, 2) ||
                    222: 
                    223:         /* memory base/limit, prefetchable base/limit and
                    224:            io base/limit upper 16 */
                    225:         ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
1.1.1.2 ! root      226:         pci_bridge_update_mappings(s);
1.1       root      227:     }
                    228: 
                    229:     newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
                    230:     if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
                    231:         /* Trigger hot reset on 0->1 transition. */
                    232:         pci_bus_reset(&s->sec_bus);
                    233:     }
                    234: }
                    235: 
                    236: void pci_bridge_disable_base_limit(PCIDevice *dev)
                    237: {
                    238:     uint8_t *conf = dev->config;
                    239: 
                    240:     pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
                    241:                                PCI_IO_RANGE_MASK & 0xff);
                    242:     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
                    243:                                  PCI_IO_RANGE_MASK & 0xff);
                    244:     pci_word_test_and_set_mask(conf + PCI_MEMORY_BASE,
                    245:                                PCI_MEMORY_RANGE_MASK & 0xffff);
                    246:     pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
                    247:                                  PCI_MEMORY_RANGE_MASK & 0xffff);
                    248:     pci_word_test_and_set_mask(conf + PCI_PREF_MEMORY_BASE,
                    249:                                PCI_PREF_RANGE_MASK & 0xffff);
                    250:     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
                    251:                                  PCI_PREF_RANGE_MASK & 0xffff);
                    252:     pci_set_word(conf + PCI_PREF_BASE_UPPER32, 0);
                    253:     pci_set_word(conf + PCI_PREF_LIMIT_UPPER32, 0);
                    254: }
                    255: 
                    256: /* reset bridge specific configuration registers */
                    257: void pci_bridge_reset_reg(PCIDevice *dev)
                    258: {
                    259:     uint8_t *conf = dev->config;
                    260: 
                    261:     conf[PCI_PRIMARY_BUS] = 0;
                    262:     conf[PCI_SECONDARY_BUS] = 0;
                    263:     conf[PCI_SUBORDINATE_BUS] = 0;
                    264:     conf[PCI_SEC_LATENCY_TIMER] = 0;
                    265: 
                    266:     /*
                    267:      * the default values for base/limit registers aren't specified
                    268:      * in the PCI-to-PCI-bridge spec. So we don't thouch them here.
                    269:      * Each implementation can override it.
                    270:      * typical implementation does
                    271:      * zero base/limit registers or
                    272:      * disable forwarding: pci_bridge_disable_base_limit()
                    273:      * If disable forwarding is wanted, call pci_bridge_disable_base_limit()
                    274:      * after this function.
                    275:      */
                    276:     pci_byte_test_and_clear_mask(conf + PCI_IO_BASE,
                    277:                                  PCI_IO_RANGE_MASK & 0xff);
                    278:     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
                    279:                                  PCI_IO_RANGE_MASK & 0xff);
                    280:     pci_word_test_and_clear_mask(conf + PCI_MEMORY_BASE,
                    281:                                  PCI_MEMORY_RANGE_MASK & 0xffff);
                    282:     pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
                    283:                                  PCI_MEMORY_RANGE_MASK & 0xffff);
                    284:     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_BASE,
                    285:                                  PCI_PREF_RANGE_MASK & 0xffff);
                    286:     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
                    287:                                  PCI_PREF_RANGE_MASK & 0xffff);
                    288:     pci_set_word(conf + PCI_PREF_BASE_UPPER32, 0);
                    289:     pci_set_word(conf + PCI_PREF_LIMIT_UPPER32, 0);
                    290: 
                    291:     pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
                    292: }
                    293: 
                    294: /* default reset function for PCI-to-PCI bridge */
                    295: void pci_bridge_reset(DeviceState *qdev)
                    296: {
                    297:     PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
                    298:     pci_bridge_reset_reg(dev);
                    299: }
                    300: 
                    301: /* default qdev initialization function for PCI-to-PCI bridge */
                    302: int pci_bridge_initfn(PCIDevice *dev)
                    303: {
                    304:     PCIBus *parent = dev->bus;
                    305:     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
                    306:     PCIBus *sec_bus = &br->sec_bus;
                    307: 
                    308:     pci_set_word(dev->config + PCI_STATUS,
                    309:                  PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
                    310:     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
                    311:     dev->config[PCI_HEADER_TYPE] =
                    312:         (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
                    313:         PCI_HEADER_TYPE_BRIDGE;
                    314:     pci_set_word(dev->config + PCI_SEC_STATUS,
                    315:                  PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
                    316: 
                    317:     qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
                    318:                         br->bus_name);
                    319:     sec_bus->parent_dev = dev;
                    320:     sec_bus->map_irq = br->map_irq;
1.1.1.2 ! root      321:     sec_bus->address_space_mem = &br->address_space_mem;
        !           322:     memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX);
        !           323:     sec_bus->address_space_io = &br->address_space_io;
        !           324:     memory_region_init(&br->address_space_io, "pci_bridge_io", 65536);
        !           325:     pci_bridge_region_init(br);
1.1       root      326:     QLIST_INIT(&sec_bus->child);
                    327:     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
                    328:     return 0;
                    329: }
                    330: 
                    331: /* default qdev clean up function for PCI-to-PCI bridge */
                    332: int pci_bridge_exitfn(PCIDevice *pci_dev)
                    333: {
                    334:     PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
                    335:     assert(QLIST_EMPTY(&s->sec_bus.child));
                    336:     QLIST_REMOVE(&s->sec_bus, sibling);
1.1.1.2 ! root      337:     pci_bridge_region_cleanup(s);
        !           338:     memory_region_destroy(&s->address_space_mem);
        !           339:     memory_region_destroy(&s->address_space_io);
1.1       root      340:     /* qbus_free() is called automatically by qdev_free() */
                    341:     return 0;
                    342: }
                    343: 
                    344: /*
                    345:  * before qdev initialization(qdev_init()), this function sets bus_name and
                    346:  * map_irq callback which are necessry for pci_bridge_initfn() to
                    347:  * initialize bus.
                    348:  */
                    349: void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
                    350:                         pci_map_irq_fn map_irq)
                    351: {
                    352:     br->map_irq = map_irq;
                    353:     br->bus_name = bus_name;
                    354: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.