(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/apb_pci.c

    1: /*
    2:  * QEMU Ultrasparc APB PCI host
    3:  *
    4:  * Copyright (c) 2006 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 deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: 
   25: /* XXX This file and most of its contests are somewhat misnamed.  The
   26:    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
   27:    the secondary PCI bridge.  */
   28: 
   29: #include "hw.h"
   30: #include "pci.h"
   31: typedef target_phys_addr_t pci_addr_t;
   32: #include "pci_host.h"
   33: 
   34: typedef PCIHostState APBState;
   35: 
   36: static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
   37:                                          uint32_t val)
   38: {
   39:     APBState *s = opaque;
   40:     int i;
   41: 
   42:     for (i = 11; i < 32; i++) {
   43:         if ((val & (1 << i)) != 0)
   44:             break;
   45:     }
   46:     s->config_reg = (1 << 16) | (val & 0x7FC) | (i << 11);
   47: }
   48: 
   49: static uint32_t pci_apb_config_readl (void *opaque,
   50:                                             target_phys_addr_t addr)
   51: {
   52:     APBState *s = opaque;
   53:     uint32_t val;
   54:     int devfn;
   55: 
   56:     devfn = (s->config_reg >> 8) & 0xFF;
   57:     val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
   58:     return val;
   59: }
   60: 
   61: static CPUWriteMemoryFunc *pci_apb_config_write[] = {
   62:     &pci_apb_config_writel,
   63:     &pci_apb_config_writel,
   64:     &pci_apb_config_writel,
   65: };
   66: 
   67: static CPUReadMemoryFunc *pci_apb_config_read[] = {
   68:     &pci_apb_config_readl,
   69:     &pci_apb_config_readl,
   70:     &pci_apb_config_readl,
   71: };
   72: 
   73: static void apb_config_writel (void *opaque, target_phys_addr_t addr,
   74:                                uint32_t val)
   75: {
   76:     //PCIBus *s = opaque;
   77: 
   78:     switch (addr & 0x3f) {
   79:     case 0x00: // Control/Status
   80:     case 0x10: // AFSR
   81:     case 0x18: // AFAR
   82:     case 0x20: // Diagnostic
   83:     case 0x28: // Target address space
   84:         // XXX
   85:     default:
   86:         break;
   87:     }
   88: }
   89: 
   90: static uint32_t apb_config_readl (void *opaque,
   91:                                   target_phys_addr_t addr)
   92: {
   93:     //PCIBus *s = opaque;
   94:     uint32_t val;
   95: 
   96:     switch (addr & 0x3f) {
   97:     case 0x00: // Control/Status
   98:     case 0x10: // AFSR
   99:     case 0x18: // AFAR
  100:     case 0x20: // Diagnostic
  101:     case 0x28: // Target address space
  102:         // XXX
  103:     default:
  104:         val = 0;
  105:         break;
  106:     }
  107:     return val;
  108: }
  109: 
  110: static CPUWriteMemoryFunc *apb_config_write[] = {
  111:     &apb_config_writel,
  112:     &apb_config_writel,
  113:     &apb_config_writel,
  114: };
  115: 
  116: static CPUReadMemoryFunc *apb_config_read[] = {
  117:     &apb_config_readl,
  118:     &apb_config_readl,
  119:     &apb_config_readl,
  120: };
  121: 
  122: static CPUWriteMemoryFunc *pci_apb_write[] = {
  123:     &pci_host_data_writeb,
  124:     &pci_host_data_writew,
  125:     &pci_host_data_writel,
  126: };
  127: 
  128: static CPUReadMemoryFunc *pci_apb_read[] = {
  129:     &pci_host_data_readb,
  130:     &pci_host_data_readw,
  131:     &pci_host_data_readl,
  132: };
  133: 
  134: static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
  135:                                   uint32_t val)
  136: {
  137:     cpu_outb(NULL, addr & 0xffff, val);
  138: }
  139: 
  140: static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
  141:                                   uint32_t val)
  142: {
  143:     cpu_outw(NULL, addr & 0xffff, val);
  144: }
  145: 
  146: static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
  147:                                 uint32_t val)
  148: {
  149:     cpu_outl(NULL, addr & 0xffff, val);
  150: }
  151: 
  152: static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
  153: {
  154:     uint32_t val;
  155: 
  156:     val = cpu_inb(NULL, addr & 0xffff);
  157:     return val;
  158: }
  159: 
  160: static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
  161: {
  162:     uint32_t val;
  163: 
  164:     val = cpu_inw(NULL, addr & 0xffff);
  165:     return val;
  166: }
  167: 
  168: static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
  169: {
  170:     uint32_t val;
  171: 
  172:     val = cpu_inl(NULL, addr & 0xffff);
  173:     return val;
  174: }
  175: 
  176: static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
  177:     &pci_apb_iowriteb,
  178:     &pci_apb_iowritew,
  179:     &pci_apb_iowritel,
  180: };
  181: 
  182: static CPUReadMemoryFunc *pci_apb_ioread[] = {
  183:     &pci_apb_ioreadb,
  184:     &pci_apb_ioreadw,
  185:     &pci_apb_ioreadl,
  186: };
  187: 
  188: /* The APB host has an IRQ line for each IRQ line of each slot.  */
  189: static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
  190: {
  191:     return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
  192: }
  193: 
  194: static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
  195: {
  196:     int bus_offset;
  197:     if (pci_dev->devfn & 1)
  198:         bus_offset = 16;
  199:     else
  200:         bus_offset = 0;
  201:     return bus_offset + irq_num;
  202: }
  203: 
  204: static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
  205: {
  206:     /* PCI IRQ map onto the first 32 INO.  */
  207:     qemu_set_irq(pic[irq_num], level);
  208: }
  209: 
  210: PCIBus *pci_apb_init(target_phys_addr_t special_base,
  211:                      target_phys_addr_t mem_base,
  212:                      qemu_irq *pic)
  213: {
  214:     APBState *s;
  215:     PCIDevice *d;
  216:     int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
  217:     PCIBus *secondary;
  218: 
  219:     s = qemu_mallocz(sizeof(APBState));
  220:     /* Ultrasparc PBM main bus */
  221:     s->bus = pci_register_bus(pci_apb_set_irq, pci_pbm_map_irq, pic, 0, 32);
  222: 
  223:     pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
  224:                                             pci_apb_config_write, s);
  225:     apb_config = cpu_register_io_memory(0, apb_config_read,
  226:                                         apb_config_write, s);
  227:     pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
  228:                                           pci_apb_write, s);
  229:     pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
  230:                                           pci_apb_iowrite, s);
  231: 
  232:     cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
  233:     cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, pci_mem_config);
  234:     cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, pci_ioport);
  235:     cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
  236: 
  237:     d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
  238:                             0, NULL, NULL);
  239:     d->config[0x00] = 0x8e; // vendor_id : Sun
  240:     d->config[0x01] = 0x10;
  241:     d->config[0x02] = 0x00; // device_id
  242:     d->config[0x03] = 0xa0;
  243:     d->config[0x04] = 0x06; // command = bus master, pci mem
  244:     d->config[0x05] = 0x00;
  245:     d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
  246:     d->config[0x07] = 0x03; // status = medium devsel
  247:     d->config[0x08] = 0x00; // revision
  248:     d->config[0x09] = 0x00; // programming i/f
  249:     d->config[0x0A] = 0x00; // class_sub = pci host
  250:     d->config[0x0B] = 0x06; // class_base = PCI_bridge
  251:     d->config[0x0D] = 0x10; // latency_timer
  252:     d->config[0x0E] = 0x00; // header_type
  253: 
  254:     /* APB secondary busses */
  255:     secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 1");
  256:     pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq, "Advanced PCI Bus secondary bridge 2");
  257:     return secondary;
  258: }
  259: 
  260: 
Syntax (Markdown)