Diff for /qemu/hw/pci.c between versions 1.1.1.4 and 1.1.1.5

version 1.1.1.4, 2018/04/24 16:43:44 version 1.1.1.5, 2018/04/24 16:46:09
Line 29  struct PCIBus { Line 29  struct PCIBus {
     int bus_num;      int bus_num;
     int devfn_min;      int devfn_min;
     pci_set_irq_fn set_irq;      pci_set_irq_fn set_irq;
       pci_map_irq_fn map_irq;
     uint32_t config_reg; /* XXX: suppress */      uint32_t config_reg; /* XXX: suppress */
     /* low level pic */      /* low level pic */
     SetIRQFunc *low_set_irq;      SetIRQFunc *low_set_irq;
     void *irq_opaque;      void *irq_opaque;
     PCIDevice *devices[256];      PCIDevice *devices[256];
       PCIDevice *parent_dev;
       PCIBus *next;
       /* The bus IRQ state is the logical OR of the connected devices.
          Keep a count of the number of devices with raised IRQs.  */
       int irq_count[];
 };  };
   
   static void pci_update_mappings(PCIDevice *d);
   
 target_phys_addr_t pci_mem_base;  target_phys_addr_t pci_mem_base;
 static int pci_irq_index;  static int pci_irq_index;
 static PCIBus *first_bus;  static PCIBus *first_bus;
   
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, void *pic, int devfn_min)  PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                            void *pic, int devfn_min, int nirq)
 {  {
     PCIBus *bus;      PCIBus *bus;
     bus = qemu_mallocz(sizeof(PCIBus));      bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
     bus->set_irq = set_irq;      bus->set_irq = set_irq;
       bus->map_irq = map_irq;
     bus->irq_opaque = pic;      bus->irq_opaque = pic;
     bus->devfn_min = devfn_min;      bus->devfn_min = devfn_min;
     first_bus = bus;      first_bus = bus;
     return bus;      return bus;
 }  }
   
   PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
   {
       PCIBus *bus;
       bus = qemu_mallocz(sizeof(PCIBus));
       bus->map_irq = map_irq;
       bus->parent_dev = dev;
       bus->next = dev->bus->next;
       dev->bus->next = bus;
       return bus;
   }
   
 int pci_bus_num(PCIBus *s)  int pci_bus_num(PCIBus *s)
 {  {
     return s->bus_num;      return s->bus_num;
 }  }
   
 void generic_pci_save(QEMUFile* f, void *opaque)  void pci_device_save(PCIDevice *s, QEMUFile *f)
 {  {
     PCIDevice* s=(PCIDevice*)opaque;      qemu_put_be32(f, 1); /* PCI device version */
   
     qemu_put_buffer(f, s->config, 256);      qemu_put_buffer(f, s->config, 256);
 }  }
   
 int generic_pci_load(QEMUFile* f, void *opaque, int version_id)  int pci_device_load(PCIDevice *s, QEMUFile *f)
 {  {
     PCIDevice* s=(PCIDevice*)opaque;      uint32_t version_id;
       version_id = qemu_get_be32(f);
     if (version_id != 1)      if (version_id != 1)
         return -EINVAL;          return -EINVAL;
   
     qemu_get_buffer(f, s->config, 256);      qemu_get_buffer(f, s->config, 256);
       pci_update_mappings(s);
     return 0;      return 0;
 }  }
   
Line 99  PCIDevice *pci_register_device(PCIBus *b Line 119  PCIDevice *pci_register_device(PCIBus *b
     pci_dev->bus = bus;      pci_dev->bus = bus;
     pci_dev->devfn = devfn;      pci_dev->devfn = devfn;
     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);      pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
       memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
   
     if (!config_read)      if (!config_read)
         config_read = pci_default_read_config;          config_read = pci_default_read_config;
Line 221  uint32_t pci_default_read_config(PCIDevi Line 242  uint32_t pci_default_read_config(PCIDevi
                                  uint32_t address, int len)                                   uint32_t address, int len)
 {  {
     uint32_t val;      uint32_t val;
   
     switch(len) {      switch(len) {
     case 1:  
         val = d->config[address];  
         break;  
     case 2:  
         val = le16_to_cpu(*(uint16_t *)(d->config + address));  
         break;  
     default:      default:
     case 4:      case 4:
         val = le32_to_cpu(*(uint32_t *)(d->config + address));          if (address <= 0xfc) {
               val = le32_to_cpu(*(uint32_t *)(d->config + address));
               break;
           }
           /* fall through */
       case 2:
           if (address <= 0xfe) {
               val = le16_to_cpu(*(uint16_t *)(d->config + address));
               break;
           }
           /* fall through */
       case 1:
           val = d->config[address];
         break;          break;
     }      }
     return val;      return val;
Line 320  void pci_default_write_config(PCIDevice  Line 348  void pci_default_write_config(PCIDevice 
         if (can_write) {          if (can_write) {
             d->config[addr] = val;              d->config[addr] = val;
         }          }
         addr++;          if (++addr > 0xff)
                   break;
         val >>= 8;          val >>= 8;
     }      }
   
Line 342  void pci_data_write(void *opaque, uint32 Line 371  void pci_data_write(void *opaque, uint32
            addr, val, len);             addr, val, len);
 #endif  #endif
     bus_num = (addr >> 16) & 0xff;      bus_num = (addr >> 16) & 0xff;
     if (bus_num != 0)      while (s && s->bus_num != bus_num)
           s = s->next;
       if (!s)
         return;          return;
     pci_dev = s->devices[(addr >> 8) & 0xff];      pci_dev = s->devices[(addr >> 8) & 0xff];
     if (!pci_dev)      if (!pci_dev)
Line 363  uint32_t pci_data_read(void *opaque, uin Line 394  uint32_t pci_data_read(void *opaque, uin
     uint32_t val;      uint32_t val;
   
     bus_num = (addr >> 16) & 0xff;      bus_num = (addr >> 16) & 0xff;
     if (bus_num != 0)      while (s && s->bus_num != bus_num)
           s= s->next;
       if (!s)
         goto fail;          goto fail;
     pci_dev = s->devices[(addr >> 8) & 0xff];      pci_dev = s->devices[(addr >> 8) & 0xff];
     if (!pci_dev) {      if (!pci_dev) {
Line 402  uint32_t pci_data_read(void *opaque, uin Line 435  uint32_t pci_data_read(void *opaque, uin
 /* 0 <= irq_num <= 3. level must be 0 or 1 */  /* 0 <= irq_num <= 3. level must be 0 or 1 */
 void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)  void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
 {  {
     PCIBus *bus = pci_dev->bus;      PCIBus *bus;
     bus->set_irq(pci_dev, bus->irq_opaque, irq_num, level);      int change;
       
       change = level - pci_dev->irq_state[irq_num];
       if (!change)
           return;
   
       pci_dev->irq_state[irq_num] = level;
       for (;;) {
           bus = pci_dev->bus;
           irq_num = bus->map_irq(pci_dev, irq_num);
           if (bus->set_irq)
               break;
           pci_dev = bus->parent_dev;
       }
       bus->irq_count[irq_num] += change;
       bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
 }  }
   
 /***********************************************************/  /***********************************************************/
Line 416  typedef struct { Line 464  typedef struct {
   
 static pci_class_desc pci_class_descriptions[] =   static pci_class_desc pci_class_descriptions[] = 
 {  {
       { 0x0100, "SCSI controller"},
     { 0x0101, "IDE controller"},      { 0x0101, "IDE controller"},
     { 0x0200, "Ethernet controller"},      { 0x0200, "Ethernet controller"},
     { 0x0300, "VGA controller"},      { 0x0300, "VGA controller"},
Line 451  static void pci_info_device(PCIDevice *d Line 500  static void pci_info_device(PCIDevice *d
     if (d->config[PCI_INTERRUPT_PIN] != 0) {      if (d->config[PCI_INTERRUPT_PIN] != 0) {
         term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);          term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
     }      }
       if (class == 0x0604) {
           term_printf("      BUS %d.\n", d->config[0x19]);
       }
     for(i = 0;i < PCI_NUM_REGIONS; i++) {      for(i = 0;i < PCI_NUM_REGIONS; i++) {
         r = &d->io_regions[i];          r = &d->io_regions[i];
         if (r->size != 0) {          if (r->size != 0) {
Line 464  static void pci_info_device(PCIDevice *d Line 516  static void pci_info_device(PCIDevice *d
             }              }
         }          }
     }      }
       if (class == 0x0604 && d->config[0x19] != 0) {
           pci_for_each_device(d->config[0x19], pci_info_device);
       }
 }  }
   
 void pci_for_each_device(void (*fn)(PCIDevice *d))  void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
 {  {
     PCIBus *bus = first_bus;      PCIBus *bus = first_bus;
     PCIDevice *d;      PCIDevice *d;
     int devfn;      int devfn;
           
       while (bus && bus->bus_num != bus_num)
           bus = bus->next;
     if (bus) {      if (bus) {
         for(devfn = 0; devfn < 256; devfn++) {          for(devfn = 0; devfn < 256; devfn++) {
             d = bus->devices[devfn];              d = bus->devices[devfn];
Line 483  void pci_for_each_device(void (*fn)(PCID Line 540  void pci_for_each_device(void (*fn)(PCID
   
 void pci_info(void)  void pci_info(void)
 {  {
     pci_for_each_device(pci_info_device);      pci_for_each_device(0, pci_info_device);
 }  }
   
 /* Initialize a PCI NIC.  */  /* Initialize a PCI NIC.  */
 void pci_nic_init(PCIBus *bus, NICInfo *nd)  void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
 {  {
     if (strcmp(nd->model, "ne2k_pci") == 0) {      if (strcmp(nd->model, "ne2k_pci") == 0) {
         pci_ne2000_init(bus, nd);          pci_ne2000_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "rtl8139") == 0) {      } else if (strcmp(nd->model, "rtl8139") == 0) {
         pci_rtl8139_init(bus, nd);          pci_rtl8139_init(bus, nd, devfn);
     } else if (strcmp(nd->model, "pcnet") == 0) {      } else if (strcmp(nd->model, "pcnet") == 0) {
         pci_pcnet_init(bus, nd);          pci_pcnet_init(bus, nd, devfn);
     } else {      } else {
         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);          fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
         exit (1);          exit (1);
     }      }
 }  }
   
   typedef struct {
       PCIDevice dev;
       PCIBus *bus;
   } PCIBridge;
   
   void pci_bridge_write_config(PCIDevice *d, 
                                uint32_t address, uint32_t val, int len)
   {
       PCIBridge *s = (PCIBridge *)d;
   
       if (address == 0x19 || (address == 0x18 && len > 1)) {
           if (address == 0x19)
               s->bus->bus_num = val & 0xff;
           else
               s->bus->bus_num = (val >> 8) & 0xff;
   #if defined(DEBUG_PCI)
           printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
   #endif
       }
       pci_default_write_config(d, address, val, len);
   }
   
   PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                           pci_map_irq_fn map_irq, const char *name)
   {
       PCIBridge *s;
       s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), 
                                            devfn, NULL, pci_bridge_write_config);
       s->dev.config[0x00] = id >> 16;
       s->dev.config[0x01] = id > 24;
       s->dev.config[0x02] = id; // device_id
       s->dev.config[0x03] = id >> 8;
       s->dev.config[0x04] = 0x06; // command = bus master, pci mem
       s->dev.config[0x05] = 0x00;
       s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
       s->dev.config[0x07] = 0x00; // status = fast devsel
       s->dev.config[0x08] = 0x00; // revision
       s->dev.config[0x09] = 0x00; // programming i/f
       s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
       s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
       s->dev.config[0x0D] = 0x10; // latency_timer
       s->dev.config[0x0E] = 0x81; // header_type
       s->dev.config[0x1E] = 0xa0; // secondary status
   
       s->bus = pci_register_secondary_bus(&s->dev, map_irq);
       return s->bus;
   }

Removed from v.1.1.1.4  
changed lines
  Added in v.1.1.1.5


unix.superglobalmegacorp.com