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

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: 
                    138: /* default write_config function for PCI-to-PCI bridge */
                    139: void pci_bridge_write_config(PCIDevice *d,
                    140:                              uint32_t address, uint32_t val, int len)
                    141: {
                    142:     PCIBridge *s = container_of(d, PCIBridge, dev);
                    143:     uint16_t oldctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
                    144:     uint16_t newctl;
                    145: 
                    146:     pci_default_write_config(d, address, val, len);
                    147: 
                    148:     if (/* io base/limit */
                    149:         ranges_overlap(address, len, PCI_IO_BASE, 2) ||
                    150: 
                    151:         /* memory base/limit, prefetchable base/limit and
                    152:            io base/limit upper 16 */
                    153:         ranges_overlap(address, len, PCI_MEMORY_BASE, 20)) {
                    154:         pci_bridge_update_mappings(&s->sec_bus);
                    155:     }
                    156: 
                    157:     newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
                    158:     if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
                    159:         /* Trigger hot reset on 0->1 transition. */
                    160:         pci_bus_reset(&s->sec_bus);
                    161:     }
                    162: }
                    163: 
                    164: void pci_bridge_disable_base_limit(PCIDevice *dev)
                    165: {
                    166:     uint8_t *conf = dev->config;
                    167: 
                    168:     pci_byte_test_and_set_mask(conf + PCI_IO_BASE,
                    169:                                PCI_IO_RANGE_MASK & 0xff);
                    170:     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
                    171:                                  PCI_IO_RANGE_MASK & 0xff);
                    172:     pci_word_test_and_set_mask(conf + PCI_MEMORY_BASE,
                    173:                                PCI_MEMORY_RANGE_MASK & 0xffff);
                    174:     pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
                    175:                                  PCI_MEMORY_RANGE_MASK & 0xffff);
                    176:     pci_word_test_and_set_mask(conf + PCI_PREF_MEMORY_BASE,
                    177:                                PCI_PREF_RANGE_MASK & 0xffff);
                    178:     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
                    179:                                  PCI_PREF_RANGE_MASK & 0xffff);
                    180:     pci_set_word(conf + PCI_PREF_BASE_UPPER32, 0);
                    181:     pci_set_word(conf + PCI_PREF_LIMIT_UPPER32, 0);
                    182: }
                    183: 
                    184: /* reset bridge specific configuration registers */
                    185: void pci_bridge_reset_reg(PCIDevice *dev)
                    186: {
                    187:     uint8_t *conf = dev->config;
                    188: 
                    189:     conf[PCI_PRIMARY_BUS] = 0;
                    190:     conf[PCI_SECONDARY_BUS] = 0;
                    191:     conf[PCI_SUBORDINATE_BUS] = 0;
                    192:     conf[PCI_SEC_LATENCY_TIMER] = 0;
                    193: 
                    194:     /*
                    195:      * the default values for base/limit registers aren't specified
                    196:      * in the PCI-to-PCI-bridge spec. So we don't thouch them here.
                    197:      * Each implementation can override it.
                    198:      * typical implementation does
                    199:      * zero base/limit registers or
                    200:      * disable forwarding: pci_bridge_disable_base_limit()
                    201:      * If disable forwarding is wanted, call pci_bridge_disable_base_limit()
                    202:      * after this function.
                    203:      */
                    204:     pci_byte_test_and_clear_mask(conf + PCI_IO_BASE,
                    205:                                  PCI_IO_RANGE_MASK & 0xff);
                    206:     pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT,
                    207:                                  PCI_IO_RANGE_MASK & 0xff);
                    208:     pci_word_test_and_clear_mask(conf + PCI_MEMORY_BASE,
                    209:                                  PCI_MEMORY_RANGE_MASK & 0xffff);
                    210:     pci_word_test_and_clear_mask(conf + PCI_MEMORY_LIMIT,
                    211:                                  PCI_MEMORY_RANGE_MASK & 0xffff);
                    212:     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_BASE,
                    213:                                  PCI_PREF_RANGE_MASK & 0xffff);
                    214:     pci_word_test_and_clear_mask(conf + PCI_PREF_MEMORY_LIMIT,
                    215:                                  PCI_PREF_RANGE_MASK & 0xffff);
                    216:     pci_set_word(conf + PCI_PREF_BASE_UPPER32, 0);
                    217:     pci_set_word(conf + PCI_PREF_LIMIT_UPPER32, 0);
                    218: 
                    219:     pci_set_word(conf + PCI_BRIDGE_CONTROL, 0);
                    220: }
                    221: 
                    222: /* default reset function for PCI-to-PCI bridge */
                    223: void pci_bridge_reset(DeviceState *qdev)
                    224: {
                    225:     PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
                    226:     pci_bridge_reset_reg(dev);
                    227: }
                    228: 
                    229: /* default qdev initialization function for PCI-to-PCI bridge */
                    230: int pci_bridge_initfn(PCIDevice *dev)
                    231: {
                    232:     PCIBus *parent = dev->bus;
                    233:     PCIBridge *br = DO_UPCAST(PCIBridge, dev, dev);
                    234:     PCIBus *sec_bus = &br->sec_bus;
                    235: 
                    236:     pci_set_word(dev->config + PCI_STATUS,
                    237:                  PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
                    238:     pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_PCI);
                    239:     dev->config[PCI_HEADER_TYPE] =
                    240:         (dev->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
                    241:         PCI_HEADER_TYPE_BRIDGE;
                    242:     pci_set_word(dev->config + PCI_SEC_STATUS,
                    243:                  PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
                    244: 
                    245:     qbus_create_inplace(&sec_bus->qbus, &pci_bus_info, &dev->qdev,
                    246:                         br->bus_name);
                    247:     sec_bus->parent_dev = dev;
                    248:     sec_bus->map_irq = br->map_irq;
                    249: 
                    250:     QLIST_INIT(&sec_bus->child);
                    251:     QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
                    252:     return 0;
                    253: }
                    254: 
                    255: /* default qdev clean up function for PCI-to-PCI bridge */
                    256: int pci_bridge_exitfn(PCIDevice *pci_dev)
                    257: {
                    258:     PCIBridge *s = DO_UPCAST(PCIBridge, dev, pci_dev);
                    259:     assert(QLIST_EMPTY(&s->sec_bus.child));
                    260:     QLIST_REMOVE(&s->sec_bus, sibling);
                    261:     /* qbus_free() is called automatically by qdev_free() */
                    262:     return 0;
                    263: }
                    264: 
                    265: /*
                    266:  * before qdev initialization(qdev_init()), this function sets bus_name and
                    267:  * map_irq callback which are necessry for pci_bridge_initfn() to
                    268:  * initialize bus.
                    269:  */
                    270: void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,
                    271:                         pci_map_irq_fn map_irq)
                    272: {
                    273:     br->map_irq = map_irq;
                    274:     br->bus_name = bus_name;
                    275: }

unix.superglobalmegacorp.com

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